C 上的联合数组

Array of Union on C

我已经声明了这个联合数组:

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

联合包含 其中一个 个成员,而不是 所有 个成员。

所以最后一个初始化器是最后一个,这意味着它的值只是 1。因此打印名称(字符串)会导致段错误,因为 printf 试图取消引用地址 1.

如果您想拥有它的所有成员,请使用 struct 而不是 union

出于某种原因,当您实际上想使用 struct 时却使用了 union。在使用它之前,您需要研究一下 union 的含义。

您的代码崩溃的原因是因为初始化:

{.name = "acos", .fnct = acos, .args = 1},

这意味着您从左到右依次写信给所有工会成员。但是由于所有成员都存储在 相同的 内存位置,这是使用 union 的全部要点,因此只有最后一个有效 1).

好的编译器会为此发出警告,因为像这样的初始化列表没有任何意义。


1)参考C11 6.7.9/17.

来自 K&R2:

""" 联合是一个变量,可以保存(在不同时间)不同类型和大小的对象,编译器会跟踪大小和对齐要求。 """

您确实在此处使用了不正确的数据结构。您应该使用 'struct' 而不是联合。

如果您有一个变量可以是一种(且只有一种)不同数据类型的选择,联合很有用。

我发现名称 'union' 具有误导性,因为数学并集暗示其所有成员的整个集合,而 C 并集不会同时包含其所有成员。此外,联合的语法与结构相同:

union u_tag {
    int ival;
    float fval;
    char *sval;
} u;

事实上,联合是结构的一种特殊情况,其中所有成员的基址偏移量为零,并且分配了足够的内存来容纳最大的成员。

快速决定是使用结构还是联合的一个经验法则是联合的所有成员都应该有相似的名称,因为它们都可以用来表示相同类型的数据(尽管有不同的数据类型)。事实上,联合体的成员具有非常不同的名称(name、fnct、args),代表完全不同类型的数据,这表明 struct 是数据结构的正确选择。