How to use c union nested in struct with no name

54,455

Solution 1

This is an anonymous union. In C++, as per [class.union], paragraph 5:

For the purpose of name lookup, after the anonymous union definition, the members of the anonymous union are considered to have been defined in the scope in which the anonymous union is declared

This means you can access its members as if they were members of RC_model_t_st.

Solution 2

Without being sure and without having tried:

The union itself is not accessible, but it's members are.

Therefore you should be able to do refer to obj.block and obj.grid

Solution 3

To elaborate on the answer provided by Angew quoting the standard concerning anonymous unions and structs, I thought to provide an sample of C source code with the output generated by that sample showing how values are allocated within a struct and a union composed of struct and union components.

The standard quoted by Angew is:

For the purpose of name lookup, after the anonymous union definition, the members of the anonymous union are considered to have been defined in the scope in which the anonymous union is declared.

The source code of a struct composed of named and anonymous structs and unions looks like the following. This is using Visual Studio 2005 and the #pragma (pack, 1) is used to align everything on a char boundary in order for there to be no memory holes. There is also a simple C Preprocessor macro defined to make the output more legible and easier to code.

typedef unsigned char UCHAR;

// use of Microsoft Visual Studio pragma to force char alignment for the struct.
#pragma pack(push, 1)
const struct {
    union {
        const UCHAR myArray[];  // this array shares memory with struct following
        struct {
            const UCHAR iOne;
            const UCHAR iTwo;
            const UCHAR iThree;
        };  // anonymous struct accessed by specifying Things.
    };      // anonymous union accessed by specifying Things.
//  const UCHAR myArray[];   // will cause error - "error C2020: 'myArray' : 'struct' member redefinition"
    union {
        const UCHAR myArray[];  // this array shares memory with struct following
        struct {
            const UCHAR iOne;
            const UCHAR iTwo;
            const UCHAR iThree;
        } s;    // named struct accessed by specifying Things.u.s
    } u;        // named union accessed by specifying Things.u
} Things = {1, 2, 4, 8, 9, 10, 22, 23, 24, 25};
#pragma pack(pop)

// a little helper macro to make the output easier to code.
#define PRINTF_VAL(x) printf ("%s %d \n", #x, x)

int itSelf (UCHAR iMask)
{
    int iMatch = -1;

    int jj = 0;
    jj = Things.myArray[0]; PRINTF_VAL(Things.myArray[0]);
    jj = Things.myArray[1]; PRINTF_VAL(Things.myArray[1]);
    jj = Things.myArray[2]; PRINTF_VAL(Things.myArray[2]);
    jj = Things.myArray[3]; PRINTF_VAL(Things.myArray[3]);
    jj = Things.myArray[4]; PRINTF_VAL(Things.myArray[4]);
    jj = Things.iOne; PRINTF_VAL(Things.iOne);
    jj = Things.iTwo; PRINTF_VAL(Things.iTwo);
    jj = Things.iThree; PRINTF_VAL(Things.iThree);

    jj = Things.u.myArray[0]; PRINTF_VAL(Things.u.myArray[0]);
    jj = Things.u.myArray[1]; PRINTF_VAL(Things.u.myArray[1]);
    jj = Things.u.myArray[2]; PRINTF_VAL(Things.u.myArray[2]);
    jj = Things.u.myArray[3]; PRINTF_VAL(Things.u.myArray[3]);
    jj = Things.u.myArray[4]; PRINTF_VAL(Things.u.myArray[4]);
    jj = Things.u.s.iOne; PRINTF_VAL(Things.u.s.iOne);
    jj = Things.u.s.iTwo; PRINTF_VAL(Things.u.s.iTwo);
    jj = Things.u.s.iThree; PRINTF_VAL(Things.u.s.iThree);

    return iMatch + 1;
}

The output generated by this function looks like:

Things.myArray[0] 1
Things.myArray[1] 2
Things.myArray[2] 4
Things.myArray[3] 8
Things.myArray[4] 9
Things.iOne 1
Things.iTwo 2
Things.iThree 4
Things.u.myArray[0] 8
Things.u.myArray[1] 9
Things.u.myArray[2] 10
Things.u.myArray[3] 22
Things.u.myArray[4] 23
Things.u.s.iOne 8
Things.u.s.iTwo 9
Things.u.s.iThree 10

The output shows the overlap between the various components of the main struct, Things caused by the use of unions. You can also see how the components of the anonymous struct and union are referenced versus those components of the named struct and union.

Also just for fun I tried adding an array definition of const UCHAR myArray[]; after the anonymous union containing const UCHAR myArray[]; to see what would happen. The compiler complained with an error of error C2020: 'myArray' : 'struct' member redefinition. The addition is commented out in the struct definition of Things above. However since the second use of const UCHAR myArray[]; is in a named union the compile works because second use is accessed by specifying the name of the union.

Solution 4

This code here (https://gist.github.com/klange/4042963) shows how to access anonymous unions inside struct. You just access the members of nested union as if they are members of the struct.

typedef struct {
    union {
        char * company;
        char * school;
        char * project;
    };
    union {
        char * location;
        char * url;
    };
    union {
        char * title;
        char * program;
    };

    time_t started;
    time_t left;

    char * description[];
} thing_t;

typedef thing_t job_t;

job_t yelp = {
    .company  = "Yelp, Inc.",
    .location = "San Francisco, CA",
    .title    = "Software Engineer, i18n",
    .started  = 1339977600,
    .left     = CURRENT,
    .description = {
        "Developed several internal tools and libraries",
        "Provided critical input and design work for Yelp's launch in Japan",
        NULL
    }
};

Solution 5

Names declared in an anonymous union are used directly, like nonmember variables. A good reason to do this is to save memory.

#include <iostream>

int main(int argc, char **argv) {
   union {
      double first;
      double second;
   };

   first = 10.001;
   second = 3.141592;
   std::cout << first << " " << second << std::endl;

   first = 10.002;
   std::cout << first << " " << second << std::endl;
}
Share:
54,455

Related videos on Youtube

zwx
Author by

zwx

Updated on February 14, 2020

Comments

  • zwx
    zwx over 4 years

    I'm working on the so called Hotspot open source project, and looking at the implementation I found a nasty nested union in struct looking like that:

    typedef struct RC_model_t_st
    {
        union
        {
            struct block_model_t_st *block;
            struct grid_model_t_st *grid;
        };
        /* block model or grid model    */
        int type;
        thermal_config_t *config;
    }RC_model_t;
    

    As far as I'm aware in C/C++ that union is unaccesible. So how someone can make use of union declared in such manner and for what purpose?

    Thanks!

  • zwx
    zwx over 11 years
    You mean that obj is RC_model_t?
  • zwx
    zwx over 11 years
    Ok. Then if I can access them as members of the structure, I don't understand why would someone put them in anonymous union?
  • zwx
    zwx over 11 years
    This is the most complete answer for me. Thanks!
  • Angew is no longer proud of SO
    Angew is no longer proud of SO over 11 years
    @zwx Because it's still a union - they occupy the same storage space.
  • Atmocreations
    Atmocreations over 11 years
    With every variable, you allocate some memory space of n bytes. Now the variables type defines only, how much space and how the content of this space is to be interpreted. With a union, the variable uses the space of the biggest type, the interpretation depends on the member you access
  • Atmocreations
    Atmocreations over 11 years
    @akp: Pay attention. Alignment could break this depending on the architecture
  • Sergey Skopus
    Sergey Skopus over 7 years
    The answer is not exact. The question was about ANONYMOUS union, the answer is about a union having a name
  • theEpsilon
    theEpsilon about 7 years
    This doesn't answer the question.
  • Brad Pitt
    Brad Pitt over 5 years
    if you put out the results of your code, that's gonna be more helpful. (though we can run it by ourself)