我无法弄清楚为什么会这样。我正在使用一堆非常复杂的结构,联合,两者的未命名版本,静态变量等......但我确信这应该有效。经过一天的调试,我已经将问题缩小到以下代码中发生的情况。我正在使用-fms-extensions,这似乎不适合这种情况:
//main.c
//Why does y get set to 0 in the case of 'Breaks'?
//Compile with gcc -fms-extensions main.c
#include <stdio.h>
struct Base {
int x;
int y;
};
struct Extend {
union {
int X;
struct Base;
};
};
struct AlsoExtend {
struct Base;
int z;
};
static struct Extend Works = {
.x = 5,
.y = 3,
//.X = 2
};
static struct Extend Breaks = {
.x = 5,
.y = 3,
.X = 2
};
static struct AlsoExtend AlsoWorks = {
.x = 5,
.y = 3,
.z = 69
};
int main(int argc, char** argv) {
printf("Works: x:%d y:%d X:%d\n", Works.x, Works.y, Works.X);
printf("Breaks: x:%d y:%d X:%d\n", Breaks.x, Breaks.y, Breaks.X);
printf("AlsoWorks: x:%d y:%d z:%d\n", AlsoWorks.x, AlsoWorks.y, AlsoWorks.z);
return 0;
}
答案 0 :(得分:5)
C99 specification说明了这一点:
当值存储在union类型的对象的成员中时,该对象的字节数 表示与该成员不对应但与其他成员对应的表示 取未指定的值。
在这里,您使用union类型的一个对象编写一个值,并在尝试访问此union类型的另一个对象之后。这会导致您的类型具有不可预测的价值。
因此,你不能做这样的事情。您只应将union的一个对象用于结构的同一实例。
答案 1 :(得分:1)
正如@lbonn所说,你在滥用C!
-fms-extensions
是GCC特定选项,它启用对非标准结构的支持,包括其他不可能的声明,例如您在上面尝试的那些。
简单的答案是:“不要那样做!”认真。不要使用-fms-extensions
,尤其不要用于您自己的代码!永远!
编写符合标准C的声明有望使问题更容易被发现。
请仔细阅读@lbonn给出的答案中引用的文字,并注意0
与未指定的值一样好。