- alignment is the reason why we can Hide data in pointer
- In general, a struct instance will have the alignment of its widest scalar member.
// assume 64-bit machine
struct foo1{
char *p; // 8 bytes
char c; // 1 bytes
long x; // 8 bytes
}
// struct foo1{
char *p; // 8 bytes
char c; // 1 bytes
char pad[7]; // 7 bytes
long x; // 8 bytes
// }
- In C, there is no leading padding, but do has trailing padding
// assume 64-bit machine
struct foo1{
char *p; // 8 bytes
char c; // 1 bytes
}
// struct foo1{
char *p; // 8 bytes
char c; // 1 bytes
char pad[7]; // 7 bytes
// }
- Inner struct padding
struct foo5 {
char c;
struct foo5_inner {
char *p;
short x;
} inner;
};
struct foo5 {
char c; /* 1 byte*/
char pad1[7]; /* 7 bytes */
struct foo5_inner {
char *p; /* 8 bytes */
short x; /* 2 bytes */
char pad2[6]; /* 6 bytes */
} inner;
};
- Save space via reorder
#include <stdio.h>
typedef struct _foo{
char x;
struct _foo *p;
short X;
} foo;
typedef struct _foo2{
struct _foo2 *p;
short X;
char x;
} foo2;
int main() {
foo myfoo;
foo2 myfoo2;
printf("%ld \n", sizeof(myfoo)); // 24
printf("%ld \n", sizeof(myfoo2)); // 16
}
-
除了 reorder 讓 size 變小之外,還必須考慮 multithreading, cache-line bouncing,以及 code readability,所以不一定是 size 越小越好。
-
Full Code
#include <stdio.h>
#include <stdbool.h>
#include <stddef.h>
/* The expected sizes in these comments assime a 64-bit machine */
struct foo1 {
char *p;
char c;
long x;
};
struct foo2 {
char c; /* 1 byte */
char pad[7]; /* 7 bytes */
char *p; /* 8 bytes */
long x; /* 8 bytes */
};
struct foo3 {
char *p; /* 8 bytes */
char c; /* 1 byte */
};
struct foo4 {
short s; /* 2 bytes */
char c; /* 1 byte */
};
struct foo5 {
char c;
struct foo5_inner {
char *p;
short x;
} inner;
};
struct foo6 {
short s;
char c;
int flip:1;
int nybble:4;
int septet:7;
};
struct foo7 {
int bigfield:31;
int littlefield:1;
};
struct foo8 {
int bigfield1:31;
int littlefield1:1;
int bigfield2:31;
int littlefield2:1;
};
struct foo9 {
int bigfield1:31;
int bigfield2:31;
int littlefield1:1;
int littlefield2:1;
};
struct foo10 {
char c;
struct foo10 *p;
short x;
};
struct foo11 {
struct foo11 *p;
short x;
char c;
};
struct foo12 {
struct foo12_inner {
char *p;
short x;
} inner;
char c;
};
int main(int argc, char *argv[])
{
printf("sizeof(char *) = %zu\n", sizeof(char *));
printf("sizeof(long) = %zu\n", sizeof(long));
printf("sizeof(int) = %zu\n", sizeof(int));
printf("sizeof(short) = %zu\n", sizeof(short));
printf("sizeof(char) = %zu\n", sizeof(char));
printf("sizeof(float) = %zu\n", sizeof(float));
printf("sizeof(double) = %zu\n", sizeof(double));
printf("sizeof(struct foo1) = %zu\n", sizeof(struct foo1));
printf("sizeof(struct foo2) = %zu\n", sizeof(struct foo2));
printf("sizeof(struct foo3) = %zu\n", sizeof(struct foo3));
printf("sizeof(struct foo4) = %zu\n", sizeof(struct foo4));
printf("sizeof(struct foo5) = %zu\n", sizeof(struct foo5));
printf("sizeof(struct foo6) = %zu\n", sizeof(struct foo6));
printf("sizeof(struct foo7) = %zu\n", sizeof(struct foo7));
printf("sizeof(struct foo8) = %zu\n", sizeof(struct foo8));
printf("sizeof(struct foo9) = %zu\n", sizeof(struct foo9));
printf("sizeof(struct foo10) = %zu\n", sizeof(struct foo10));
printf("sizeof(struct foo11) = %zu\n", sizeof(struct foo11));
printf("sizeof(struct foo12) = %zu\n", sizeof(struct foo12));
if (sizeof(struct foo3) == 16) {
puts("This looks like a 64-bit machine.");
} else if (sizeof(struct foo3) == 6) {
puts("This looks like a 32-bit machine.");
} else {
puts("Huh? The word size of this mahine is not obvious");
}
if ((offsetof(struct foo1, x) % sizeof(long)) == 0) {
puts("Self-alignment seems to be required.");
} else {
puts("Self-alignment test of type long failed.");
}
}
sizeof(char *) = 8 sizeof(long) = 8 sizeof(int) = 4 sizeof(short) = 2 sizeof(char) = 1 sizeof(float) = 4 sizeof(double) = 8 sizeof(struct foo1) = 24 sizeof(struct foo2) = 24 sizeof(struct foo3) = 16 sizeof(struct foo4) = 4 sizeof(struct foo5) = 24 sizeof(struct foo6) = 8 sizeof(struct foo7) = 4 sizeof(struct foo8) = 8 sizeof(struct foo9) = 12 sizeof(struct foo10) = 24 sizeof(struct foo11) = 16 sizeof(struct foo12) = 24 This looks like a 64-bit machine. Self-alignment seems to be required.