0
#include <iostream>
union xxx
{
  uint64_t f5;
  char f4;
  struct
  {
    char f1;
    uint32_t f2;
    char f3[3];
  } abc;
};

union xxx2
{
  uint64_t f5;
  char f4;
};

struct xxx3
{
    char c;
    uint32_t c2;
};

struct xxx4
{
    char c;
    uint32_t c2;
    char c3;
};

int main()
{
    std::cout << sizeof(union xxx) << std::endl;  // 16
    std::cout << sizeof(xxx::abc) << std::endl;   // 12
    std::cout << sizeof(union xxx2) << std::endl;   // 8
    std::cout << sizeof(xxx3) << std::endl;   // 8
    std::cout << sizeof(xxx4) << std::endl;   // 12

    return 0;
}

Question> The size of a union is sufficient to contain the largest of its data members. The largest data member inside xxx is abc which is of size 12 bytes. Why the sizeof xxx is 16 instead of 12?

q0987
  • 34,938
  • 69
  • 242
  • 387
  • 5
    Alignment and padding. There's a duplicate for this question. – user0042 Oct 10 '17 at 19:59
  • @user0042 I don't understand why we need alignment and padding for 12. – q0987 Oct 10 '17 at 20:02
  • 3
    Is 12 a multiple of 8? – user0042 Oct 10 '17 at 20:03
  • Why we have to make alignment based on 8? Is it because we have a member with size uint64_t? I thought 12 is a multiple of 4 so no padding is required. but I was wrong here. – q0987 Oct 10 '17 at 20:05
  • @q0987: If you rearrange your members of `abc`, you can get it to be smaller: [demo](https://wandbox.org/permlink/9yvi7lPTJthLsPbb) – AndyG Oct 10 '17 at 20:05
  • @AndyG, I understand the padding and alignment and the rearrange will change the size. Just for this question, I need to see why the compiler insists an 8 bytes alignments. – q0987 Oct 10 '17 at 20:07
  • 2
    @q0987 It realizes that that is the most efficient way to access the union's elements on your platform, that's all. – Rakete1111 Oct 10 '17 at 20:09
  • @q0987: I found the following article immensely instructing: http://www.catb.org/esr/structure-packing/#_alignment_requirements – AndyG Oct 10 '17 at 20:10
  • @Rakete1111, please check my updated post. If you look the sizeof xxx4, then I don't understand why the compiler doesn't pad it to 16. Instead, the sizeof xxx4 is 12! It seems the compiler pads the size based on the largest element in the struct. – q0987 Oct 10 '17 at 20:11
  • @q0987 What's your platform? That question is a bit impossible to answer. Also, I would expect it to be 6 (and thus 8) but I also have no idea :P You can (probably) trust the compiler. – Rakete1111 Oct 10 '17 at 20:16
  • 1
    @q0987: because xxx4 has 4 byte alignment, the result is 3 bytes of slop after `c` and 3 more bytes of slop after `c3`. 1 + 3 + 4 + 1 +3 = 12 – AndyG Oct 10 '17 at 20:18
  • 1
    Which is why reordering means less slop. If you reorder so that the 2 chars are together, then you only have 2 bytes of padding, for a total size of 8 [Demo](https://wandbox.org/permlink/VCry4B3KRId2w8um) – AndyG Oct 10 '17 at 20:20
  • @AndyG, xxx4 has 4 byte alignment and union xxx has 8. It seems to me the alignment size is based on the largest element defined in the struct. – q0987 Oct 10 '17 at 20:20
  • @q0987: Bingo. Now if you'd just read the article I'd linked. – AndyG Oct 10 '17 at 20:21

0 Answers0