Search code examples
cstructureunions

C- Structures and Unions


C standard states that only the members of a union are stored at the same address and ,because of which, we can access only one member at a time.Since the compiler overlays storage for the members of a union, changing one member alters any value previously stored in any of the other members.So if we try to access the value of a member stored previously, the value will be meaningless or undefined.Now here is my question:-

struct catalog_item
{
   int stock_number;
   double price;
   int item_type;
   union
     {
       struct
          {
            char title[TITLE_LEN+1];
            char author[AUTHOR_LEN+1];
            int num_pages;
          } book;
       struct
          {
            char design[DESIGN_LEN+1];
          } mug;
       struct
          {
            char design[DESIGN_LEN+1];
            int colors;
            int sizes;
          } shirt;
     } item;
} c;

Now if the following is done

strcpy(c.item.mug.design, "Butterfly");

then both of the following have the same value

printf("%s",c.item.mug.design);          //1

and

printf("%s",c.item.shirt.design);        //2

Why is the result of "2" is not undefined or meaningless?


Solution

  • This is not undefined behavior but it is implementation defined behavior, if we look at the C99 draft standard footnote 82 says:

    If the member used to access the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called "type punning"). This might be a trap representation.

    In practice this is supported in C and you should read the specific compilers documentation. For example if you examine the Implementation-defined behavior section for Structures, unions, enumerations, and bit-fields in the gcc manual it points to here for Type-punning and we can see under the -fstrict-aliasing section is says:

    The practice of reading from a different union member than the one most recently written to (called “type-punning”) is common. Even with -fstrict-aliasing, type-punning is allowed, provided the memory is accessed through the union type.

    but there are caveats and you should read up on strict aliasing to understand all the details, this article is gentler introduction.

    For completeness section 3.4.1 defines implementation-defined behavior as:

    unspecified behavior where each implementation documents how the choice is made

    and the standard annex J.1 Unspecified behavior which lists the unspecified behavior covered by the standard includes this line:

    The value of a union member other than the last one stored into (6.2.6.1).