2

I'm very confused by the whole 'data alignment' thing:

#include <stdio.h>
int main(){
    struct st{
        int i,*p;
        char c;
        union { char type[4]; unsigned char d;} un; 
    };

    struct st s1={25,&a,'X',"asdf"};
    printf("sizeof s1 is %d",sizeof(s1));
    return 0;
}

due to data alignment, i thought that since the sizes of

int i : 4 bytes
int *p : 8 bytes
char c : 1 byte(+3)
union : 4 bytes

the output would be 20, but this outputs sizeof s1 is 24! Why is it outputting 24? Does this regard int *p, which is 8 bytes?

Tim Dean
  • 8,253
  • 2
  • 32
  • 59
  • 2
    The `sizeof` a `struct` (how much memory is allocated to it) isn't necessarily the sum of the size of its parts. The compiler may pad parts of it (moreso than you indicated). Or it may round it to a multiple of 8. See, for example, http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member – lurker Dec 12 '13 at 03:14
  • Given the answers below, you should put the declaration of `p` first, or check whether your compiler has relevant `#pragma`s. – Eric Jablow Dec 12 '13 at 03:21
  • @EricJablow: If you put `p` first the size will still be 24. You can check it yourself. – Dietrich Epp Dec 12 '13 at 03:22
  • The question I have proposed as an original asks about C++, but it involves only plain old data, so it covers the C case. – Eric Postpischil Dec 12 '13 at 03:37

2 Answers2

2

On your system, pointers are 8 bytes and aligned to 8 bytes.

  1   2   3   4   5   6   7   8
+---+---+---+---+---+---+---+---+
| int i         | [pad]         |
+---+---+---+---+---+---+---+---+

  9  10  11  12  13  14  15  16
+---+---+---+---+---+---+---+---+
| int *p                        |
+---+---+---+---+---+---+---+---+

 17  18  19  20  21  22  23  24
+---+---+---+---+---+---+---+---+
| c | un            | [pad]     |
+---+---+---+---+---+---+---+---+

Of course, you cannot be sure of the exact layout without knowing the ABI. The above is only an example.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
0

On the architecture you're using, the int *p is 8 bytes, but needs to be on an 8 byte boundary also. That gives you 4 bytes pad between i and p. Furthermore, because int *p needs to be on an 8 byte boundary, the overall structure needs to be a multiple of 8 bytes so that an array of them always has the right alignment for p.

So, you end up with a layout like this:

  • i: 4 bytes, alignment 4
  • pad: 4 bytes
  • p: 8 bytes, alignment 8
  • c: 1 bytes
  • un: 4 bytes (as it can remain byte aligned)
  • pad: 3 bytes (to round it out to an 8 byte boundary)
Joe Z
  • 17,413
  • 3
  • 28
  • 39
  • so in all structures do the size always round up to the largest component in size? – lessofaprogrammer Dec 12 '13 at 03:20
  • It depends on many things. – Dietrich Epp Dec 12 '13 at 03:21
  • @user3093640 : On the architectures I've worked with, generally the alignment of a `struct` matches the alignment of the most restrictive member of the `struct`. It's implementation defined, though. Length and alignment requirement don't always match: On 32-bit x86 for example, the `long long` type is 8 bytes, but only has alignment requirement of 4 bytes. – Joe Z Dec 12 '13 at 03:21