1
struct One{
       int x[6];
       short y[12];
} a;

union Two{
       int x[6];
       short y[12];
} b;

Assume that ints are 32 bits, and that shorts are 16 bits.

a. What is the sizeof(a) and sizeof(b)?

b. if &a = 0x00320000, what is &a.y?

c. if &b = 0x00320400, what is &b.y?

Could someone please explain how to derive at the size of the union and struct, as well as how to get the values for the addresses. I understand that &a and &b mean the address of a and b respectively. However, i'm not exactly sure how to derive at what &a.y and &b.y will return.

Natan Streppel
  • 5,759
  • 6
  • 35
  • 43
petrov
  • 1,085
  • 3
  • 12
  • 13
  • 2
    Why don't you compile and check yourself. – Ankur Apr 03 '14 at 17:16
  • What is the fundamental difference between a structure and a union? That will largely control the answers — and is what the homework is driving at. Succinctly, the size of a union is the size of its largest element; the size of a structure is the sum of the sizes of its elements, plus padding where needed. – Jonathan Leffler Apr 03 '14 at 17:18
  • Even given the bit counts for each type, this is still compiler- and system-dependent. – Thomas Apr 03 '14 at 17:18
  • Do you want a language-lawyer answer or an answer for soe specific implementation only? – Deduplicator Apr 03 '14 at 17:19
  • 1
    @Shan: Damnit, don't reinforce such bad ideas. They only hold for one specific implementation, and maybe only until the next most minor bugfix in source/compiler/OS/whathaveyou. – Deduplicator Apr 03 '14 at 17:32

3 Answers3

4

a. You don't know. That's what sizeof(struct One) is for. It is a common misconception to believe that the size of a structure is the sum of its elements - the implementation can pad the structure at any point (except in the beginning) for alignment reasons - The implementation can pad the structure after any member by any amount, though two structures starting with the same initial types have the corresponding members at the same offsets (as pointed out in a comment). For the union, it is the size of the largest field, i.e., max(sizeof(b.x), sizeof(b.y)).

b. and c. Use the macro offsetof() as a portable way to find the offset of fields in a structure. &a.y is just ((char *) a)+offsetof(struct One, y). For the union, both &b, &b.x and &b.y are the same.

EDIT: There are compiler-specific options that you can use to control padding and alignment. See, for example, gcc's structure padding pragmas.

Filipe Gonçalves
  • 20,783
  • 6
  • 53
  • 70
  • Perhaps change to: The implementation can padd the structure after any member however much it wants, though two structures starting with the same initial types have the corresponding members at the same offsets... – Deduplicator Apr 03 '14 at 17:21
  • @Deduplicator Correct, I agree. Edited. – Filipe Gonçalves Apr 03 '14 at 17:26
  • So just to verify that my thought process is correct. sizeof(a) would be (32*6) + (16*12) = 384. and the sizeof(b) would be 32*6 = 192. Then for the offset, &a.y 0x00320016 and for &b.y it would remain 0x00320400. Correct? – petrov Apr 03 '14 at 17:39
  • `sizeof a >= 6*sizeof(int)+12*sizeof(short)`. sizeof gives the size in bytes (`char`). Use `CHAR_BITS` if you need to move to bitcount. – Deduplicator Apr 03 '14 at 17:47
  • You might want to add that there are compiler-specific options/directives for enforcing specific padding and alignment rules. This doesn't detract from you original point though. – Cloud Apr 03 '14 at 18:05
  • @petrov If you assume there is no padding, and that `sizeof(int) == 4`, `sizeof(short) == 2`, and `CHAR_BIT == 8`, then yes, `sizeof(a)` is 384 and `sizeof(b)` is 192. However, `&a.y` would be `0x00320018`: the offset of `y` is 4*6 = 24 bytes, and 24 in hex is 18. – Filipe Gonçalves Apr 03 '14 at 18:06
  • @Dogbert Done. I personally am not familiar with compilers other than gcc, but feel free to leave a comment with more examples if you want. – Filipe Gonçalves Apr 03 '14 at 18:09
1

Even though, for the most part, the answers are implementation-defined, a programmer for debugging and trouble-shooting needs to know what the (likely) answers are, on his/her platform:

a. What is the sizeof(a) and sizeof(b)?

sizeof a = 6 * 4 + 12 * 2 = 48. Important: if you change 12 to 13, this calculation would likely be wrong, as padding would typically be added, probably 2 bytes, and so the size of the struct would not be the sum of the sizes of its elements.

sizeof b = max(6 * 4, 12 * 2) = 24, because in this union, x and y are overlayed. Again if you change 12 to 13, there's likely padding.

b. if &a = 0x00320000, what is &a.y?

&a.y = 0x00320000 + 6 * 4 = 0x00320018

c. if &b = 0x00320400, what is &b.y?

&b.y = &b (guaranteed)

Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
0

a.) Size of A will be the sizeof(int) * 6 + sizeof(short) * 12, or 72 bytes (possibly plus a few bytes for alignment). Whereas the size of b will be 48, the size of the largest member. Basically unions are used as a means of aliasing the same memory space, as such the compiler must use the size of the largest member when determining how much space the union will take in memory.

b.) The address will be 0x00320018.

c.) The address will be 0x00320400 because both b.X and b.Y are stored at the same location.

R M
  • 96
  • 1
  • 4