Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access a struct member inside a union in C?

I have the following union:

union employee
{
    char key;

    struct manager
    {
        short int age;
        float shares;
        short int level;
    };

    struct worker
    {
        short int age;
        short int skill;
        short int department;
    };

} company[10];

How can I access a member of a structure which is inside the union employee? I tried to access the age member of the manager structure this way:

company[i].manager.age

But I get error C2039: 'manager' : is not a member of 'employee'.

like image 742
amiregelz Avatar asked Sep 29 '12 14:09

amiregelz


2 Answers

Add something after the tag declaration. Perhaps:

struct manager
{
    short int age;
    float shares;
    short int level;
} manager;

Side note: you're not using the union right. The key, i.e. the field that tells you whether you are dealing with a manager or with a mere worker should be in an enclosing object, outside the union. Perhaps:

struct employee {
    char key;

    union {
        struct manager ...;
        struct worker ...;
    } u;
};

As dasblinkenlight notes, you could declare your manager / worker tags outside the union.

like image 163
cnicutar Avatar answered Oct 20 '22 06:10

cnicutar


Anonymous structs/unions is not part of the C standard, but rather a not very widespread GNU extension.

In your particular example some compilers (mainly GCC) will allow you to access manager and worker unique variables via e.g. company[i].shares or company[i].department, but company[i].age is ambiguous and the compiler will not know which one is meant. Your approach is similar to trying to define

 union {
      int num;
      float num;
 } union_number;

which is not even valid C.

there are two ways to solve this.

a) moving the shared attributes outside the struct (the evil GNU way, please don't do that, I know for a fact that icc does not even compile this)

union employee
{
    char key;

    struct person {
        short int age;

        union {
            struct manager
            {
                float shares;
                short int level;
            };

            struct worker
            {
                short int skill;
                short int department;
            };
        }
    };

} company[10];

b) or the more clean standardized way to name your structs:

union employee
{
    char key;

    struct manager
    {
        short int age;
        float shares;
        short int level;
    } manager;

    struct worker
    {
        short int age;
        short int skill;
        short int department;
    } worker;

} company[10];

in this case you will be able to access the struct elements via company[i].manager.age, company[i].worker.skill and so on.

Please pay attention that at runtime there is no way to test whether your union contains a key, a manager or a worker. That must be known in advance.

Another thing: I am not sure if this is intended, but in your declaration you cannot save a key together with a manager or a worker. Your union contains only one of key, manager or worker

like image 24
Sergey L. Avatar answered Oct 20 '22 07:10

Sergey L.