Search code examples
c++structunions

Byte size of union and struct


 #include <iostream>
 using namespace std;
 typedef union {
            long i;
            int k[5];
            char c;
 } UDATE;
 struct data {
            int cat;
            UDATE cow;
            double dog;
  } too;
 UDATE temp;
 int main()
 {
        cout << sizeof(struct data)+sizeof(temp) << endl;
        return 0;
  }

under ubuntu 18.04, the answer to this question is 64, but I want to know how uDATE cow in struct is stored in memory, or the rules of data storage?


Solution

  • According to the C++ standard:

    The size of a union is sufficient to contain the largest of its data members. Each data member is allocated as if it were the sole member of a struct.

    So the memory layout of the union is the same as if you had a long there, an array of 5 ints there, or a char there, but spaced to the largest of these (the array of ints). I presume you're using GCC, and IIRC GCC sets a size of 32-bits for int even on a 64-bit architecture. UDATE would therefore have a size of 20-bytes. You'd naively expect, therefore, sizeof(struct data) + sizeof(temp) to return 52. The fact that you're apparently getting 64 is probably because GCC is aligning things to 64-bit boundaries and thus taking 24-bytes for UDATE, and inserting a 4-byte spacer between cat and cow in your data struct.

    Note that the standard makes no guarantees made about type-punning - that is the frequently used low level technique where the union is written using one method and read using another to, for example, access the bytes that make up an integer - and claims that a union may only be accessed using the same entries that it was written using (baring an exception for a union of POD structs that share common initial members). However, in practice every compiler I've ever used will read the memory in the manner you'd expect if you'd simply cast a pointer from one type to another in the union using a reinterpret or C-style cast.