Проверка типов в постоянном анонимном союзе
Прежде всего, проверка типов не совсем правильный термин, который я ищу, поэтому я объясню: скажем, я хочу использовать анонимное объединение, я делаю объявление объединения в структуре const
, поэтому после инициализации значения не изменятся. Это должно позволить статически проверять, осуществляется ли доступ к неинициализированному члену объединения. В приведенном ниже примере экземпляры инициализируются для a
(int) или b
(С плавающей точкой). После этой инициализации я бы не хотел иметь доступ к другому члену:
struct Test{
const union{
const int a;
const float b;
};
};
int main(){
struct Test intContainer = { .a=5 };
struct Test floatContainer = { .b=3.0 };
int validInt = intContainer.a;
int validFloat = floatContainer.b;
// For these, it could be statically determined that these values are not in use (therefore invalid access)
int invalidInt = floatContainer.a;
float invalidFloat = intContainer.b;
return 0;
}
Я хотел бы получить последние два назначения, чтобы выдать ошибку (или хотя бы предупреждение), но она не дает ничего (с помощью gcc 4.9.2). C предназначен, чтобы не проверять это, или это на самом деле недостаток языка / компилятора? Или просто глупо хотеть использовать такой шаблон?
На мой взгляд, у меня есть большой потенциал, если бы это была особенность, поэтому кто-то может объяснить мне, почему я не могу использовать это как способ различать два "подтипа" одной и той же структуры (один для каждое объединенное значение). (Потенциально есть какие-нибудь предложения, как мне все-таки сделать что-то подобное?)
РЕДАКТИРОВАТЬ: Таким образом, очевидно, что это не в стандарте языка, и компиляторы не проверяют это. Тем не менее, я лично считаю, что это было бы неплохо, так как это исключает ручную проверку union
содержимое с использованием теговых союзов. Итак, мне интересно, у кого-нибудь есть идея, почему он не представлен в языке (или это компиляторы)?
1 ответ
Я хотел бы получить последние два назначения, чтобы выдать ошибку (или хотя бы предупреждение), но она не дает ничего (с помощью gcc 4.9.2). C предназначен, чтобы не проверять это, или это на самом деле недостаток языка / компилятора?
Это правильное поведение компилятора.
float invalidInt = floatContainer.a;
float invalidFloat = intContainer.b;
В первом объявлении вы инициализируете float
объект с int
значение и во втором вы инициализируете float
объект с float
значение. В C вы можете назначать (или инициализировать) любые арифметические типы любым арифметическим типам без каких-либо приведений. Так что никакой диагностики не требуется.
В вашем конкретном случае вы также читаете union
члены, которые не являются теми же членами, что и union
Последний член использовался для хранения его значения. Предполагая, что union
члены имеют одинаковый размер (например, float
а также int
здесь), это определенное поведение, и никакая диагностика не требуется. Если размер union
члены разные, поведение не определено (но все же, диагностика не требуется).