A question I have on Problem 3.44 of the book Computer Systems: A Programmer's Perspective (3rd edition (6 October 2015)) on data alignment.
The problem:
For each of the following structure declarations, determine the offset of each feild, the total size of the structure, for 8-bit alignment:
struct P1 {short i; int c; int *j; short *d}
...
struct P4 {char w[16]; char *c[2]}
struct P5 {struct P4 a[2]; struct P1 t}
Answer given in the book:
- struct P1:
i | c | j | d | total |
---|---|---|---|---|
0 | 2 | 6 | 14 | 16 |
- struct P4:
w | c | total |
---|---|---|
0 | 16 | 32 |
- struct P5:
a | t | total |
---|---|---|
0 | 24 | 40 |
What I don't get is why did struct P4 a[2]
in P5
only takes 24 bytes?
Since P5.a
is an array of P4
of size 2, shouldn't it occupy 2 * 32 (total size of P4)
bytes?
To make sure I quote the book correctly, attaching the screenshots below:
CodePudding user response:
P1 is wrong. In case
int* j
occupies 8 bytes, then on any known real-world computer with 64 bit addressing,short* d
will also occupy 8 bytes. For a total of 22 bytes, assuming no padding was inserted afteri
, which is unlikely. In case padding is inserted, the total size would be 24 bytes.On a real-world 64 bit system, the struct layout would be:
short i size: 2 offset: 0 int c size: 4 offset: 4 int* j size: 8 offset: 8 short* d size: 8 offset: 16
-
What I don't get is why did struct P4 a[2] in P5 only takes 24 bytes?
It doesn't.
P4
= 32 bytes, no padding. 2 * 32 = 64 bytes.P5
will be 64 24 = 88 bytes.
If you are quoting the book correctly, then evidently it has not been proof-read from the programmer's perspective...
CodePudding user response:
A code to test: (Gives the occupation in structure, not the size).
#include <stdio.h>
struct P1
{
short i;
int c;
int *j;
short *d;
long long end[];
};
struct P4
{
char w[16];
char *c[2];
long long end[];
};
struct P5
{
struct P4 a[2];
struct P1 t;
long long end[];
};
int main(void)
{
struct P1 p1;
printf("size of p1 : %zu\n", sizeof(p1));
printf("short i : %zu\n", (size_t)&p1.c - (size_t)&p1.i);
printf("int c : %zu\n", (size_t)&p1.j - (size_t)&p1.c);
printf("int *j : %zu\n", (size_t)&p1.d - (size_t)&p1.j);
printf("short *d : %zu\n", (size_t)&p1.end - (size_t)&p1.d);
struct P4 p4;
printf("\nsize of p4 : %zu\n", sizeof(p4));
printf("char w[16] : %zu\n", (size_t)&p4.c - (size_t)&p4.w);
printf("char *c[2] : %zu\n", (size_t)&p4.end - (size_t)&p4.c);
struct P5 p5;
printf("\nsize of p5 : %zu\n", sizeof(p5));
printf("struct P4 a[2] : %zu\n", (size_t)&p5.t - (size_t)&p5.a);
printf("struct P1 t : %zu\n", (size_t)&p5.end - (size_t)&p5.t);
return 0;
}
- The flexible member array is just to mark the end.