6

I have declared this array of 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},
};

But, when I try to use it I get an Segmentation fault error.

for(int i = 0; i < sizeof(functions) / sizeof(union Function); i++) {
    printf("%d\n", functions[i].args);
    printf("%s\n", functions[i].name); //HERE!
}
stefanobaghino
  • 11,253
  • 4
  • 35
  • 63
Pablo
  • 63
  • 1
  • 1
  • 3

3 Answers3

11

A union contains either of its members, not all of its members.

So the last initializer is the final one, meaning its value is just 1. So printing the name ( a string) results in a seg fault because printf tries to dereference the address 1.

If you want to have all of its members, use struct instead of union.

iBug
  • 35,554
  • 7
  • 89
  • 134
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
4

For some reason you are using a union when you actually want to use a struct. You need to study what union means before you can use it.

The reason your code is crashing, is because of the initialization:

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

This means that you write to all union members in turn, from left to right. But since all members are all stored at the same memory location, which is the whole point of using union, only the last one will be valid 1).

A decent compiler will give you a warning for this, since an initialization list like this does not make any sense.


1) Reference C11 6.7.9/17.

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

From K&R2:

""" A union is a variable that may hold (at different times) objects of different types and sizes, with the compiler keeping track of size and alignment requirements. """

You're indeed using the incorrect data structure here. You should be using a 'struct' instead of a union.

A union is useful if you have a variable that could be one (and only one) kind of a choice of differing data types.

I find the name 'union' misleading since a mathematical union implies the entire collection of all its members, whereas a C union does not contain all its members at once. Furthermore, the syntax for a union is identical to a struct:

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

Infact, a union is a special case of a struct where all members have offset zero from the base and sufficient memory is allocated to hold the biggest member.

One rule of thumb to quickly decide whether to use a struct or a union is that all members of a union should have similar names, as they can all be used to represent the same kind of data (albeit with a differing data type). The fact that the members of your union have very different names (name, fnct, args) representing entirely different kinds of data, is a give away that a struct is the right choice of data structure.

laker93
  • 498
  • 4
  • 9