tags:

views:

41

answers:

3

Can anyone please explain why the 1st method of accessing a nested struct element inside an union in a struct works and the 2nd does not?

typedef struct element Node;
struct element
{
    int type;
    union
    {
        int value;
        Node *child[2];
    } u;
};
int main()
{
    Node n;
    Node *p;    
    n.type = 0;
    p = n.u.child[0];
    p->type = 10;  // 1st method
    (n.u.child[1])->type = 24;   // 2nd method
    return 0;
}
+1  A: 

Either of those methods should be fine for accessing a nested struct element inside a union, the issue here is that you haven't allocated memory for the nodes referred to by child[0] or child[1]. (I'm surprised your "1st method" doesn't fail, too.)

Mark E
The 1st method does work and that's the reason why I got confused when the 2nd one doesn't.
Nitzs
+1  A: 

Try the following:

int main()
{
    Node n;
    Node *p;    
    n.type = 0;

    // allocate memory for child nodes
    n.u.child[0] = (Node *)malloc(sizeof(Node));

    if (n.u.child[0] == NULL)
    {
        return 1;
    }

    n.u.child[1] = (Node *)malloc(sizeof(Node));

    if (n.u.child[1] == NULL)
    {
        free(n.u.child[0]);
        return 1;
    }

    p = n.u.child[0];
    p->type = 10;  // 1st method
    (n.u.child[1])->type = 24;   // 2nd method

    // release dynamically allocated memory
    free(n.u.child[0]);
    free(n.u.child[1]);

    return 0;
}

NOTE: Don't modify n.u.value of a Node if you've already assigned its child[] pointers. You will overwrite one of the pointers and leak that memory as well as crash if you try to access the child[] array after that. Unions are tricky -- best to avoid this sort of arrangement.

Amardeep
Thanks for your reply, Amardeep. I do know that one needs to allocate memory to a pointer object before accessing it. But in this case, without allocating any memory to either of the child nodes, why only does the 2nd method fail when both should in the ideal case.
Nitzs
ANSI C does not initialize structures you allocate on the stack. So the array n.u.child[] contained two pointers with indeterminate values. It just happens that child[0] contained a value that pointed to a memory address which didn't cause a crash when you dereferenced and wrote to it. You can't count on that behavior and you don't know what was corrupted when you did that assignment.
Amardeep
Thanks. Got it.
Nitzs
A: 

Your problem has not much to do with the fact that there are unions involved.

Accessing uninitialized pointers just gives you random behavior. Sometimes it does work sometimes not. For your first access probably something just luckily happened to be in the place that you access.

Just initialize, à la C99:

Node n = { .type = 0 };

or

Node n = { 0 };

à la C89, instead of your assignment statement. This has the advantage to initialize all components that are not mentioned to 0, thus your pointers. Then your test code should segfault happily ever after.

Jens Gustedt