首先,类型检查并不是我正在寻找的正确术语,所以我将解释:
假设我想使用匿名联合,我在struct const
中创建了union声明,因此在初始化之后,值不会改变。这应该允许静态检查是否正在访问联合的未初始化成员。在下面的示例中,为a
(int)或b
(float)初始化实例。在初始化之后,我希望无法访问其他成员:
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是否设计为不检查这个,还是它实际上是语言/编译器的缺点?或者想要使用这种模式只是愚蠢吗?
在我看来,如果这是一个功能,它看起来有很大的潜力,所以有人可以向我解释为什么我不能用它来区分两个"子类型& #34;一个相同的结构(每个联合值一个)。 (可能有任何建议我仍然可以做这样的事情吗?)
编辑:
显然它不符合语言标准,编译器也不会检查它。我个人认为这是一个很好的功能,因为它只是消除了使用标记的联合手动检查union
的内容。所以我想知道,有没有人知道它为什么没有语言特色(或者它的编译器)?
答案 0 :(得分: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
成员的大小不同,则行为未指定(但仍然不需要诊断)。