C上的联盟数组

时间:2018-01-26 12:20:40

标签: c arrays unions

我已经宣布了这个联盟阵列:

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!
}

3 个答案:

答案 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)非常不同,这一事实是一个结构是数据结构的正确选择。