我已经宣布了这个联盟阵列:
union Function {
char* name;
double (*fnct)();
int args;
};
union Function functions[] = {
{.name = "acos", .fnct = acos, .args = 1},
{.name = "asin", .fnct = asin, .args = 1},
{.name = "atan", .fnct = atan, .args = 1},
};
但是,当我尝试使用它时,我收到了分段错误。
for(int i = 0; i < sizeof(functions) / sizeof(union Function); i++) {
printf("%d\n", functions[i].args);
printf("%s\n", functions[i].name); //HERE!
}
答案 0 :(得分:9)
联盟包含其成员的 ,而不是其成员的所有。
所以最后一个初始化器是最后一个,意味着它的值只是1
。因此,打印名称(字符串)会导致seg错误,因为printf
会尝试取消引用地址1
。
如果您想拥有所有成员,请使用struct
代替union
。
答案 1 :(得分:3)
出于某种原因,当您确实想要使用union
时,您使用的是struct
。在使用它之前,您需要研究union
的含义。
您的代码崩溃的原因是由于初始化:
{.name = "acos", .fnct = acos, .args = 1},
这意味着您从左到右依次写入所有工会成员。但由于所有成员都存储在相同的内存位置,这是使用union的全部要点,只有最后一个成员才有效 1)。
一个不错的编译器会给你一个警告,因为像这样的初始化列表没有任何意义。
1)参考文献C11 6.7.9 / 17.
答案 2 :(得分:0)
来自K&amp; R2:
&#34;&#34;&#34; 联合是一个变量,可以保存(在不同的时间)不同类型和大小的对象,编译器跟踪大小和对齐要求。 &#34;&#34;&#34;
您确实在这里使用了错误的数据结构。你应该使用&#39;结构&#39;而不是工会。
如果你有一个变量可以是一种(并且只有一种)不同数据类型的选择,那么联合很有用。
我找到了名字&#39; union&#39;误导,因为数学联盟意味着其所有成员的整个集合,而C联盟并不立即包含其所有成员。此外,union的语法与struct:
相同union u_tag {
int ival;
float fval;
char *sval;
} u;
事实上,union是一个结构的特例,其中所有成员都从基数偏移零,并且分配了足够的内存来容纳最大的成员。
快速决定是使用结构还是联合的一条经验法则是,联合的所有成员都应该具有相似的名称,因为它们都可以用于表示相同类型的数据(尽管数据类型不同) )。你的union的成员有完全不同类型的数据的名称(name,fnct,args)非常不同,这一事实是一个结构是数据结构的正确选择。