前言
在阅读《深入理解计算机系统》这本书的时候,看到了 C 语言中的结构体字节对齐,在此以 x86-64 架构为例,记录一下 Linux gcc 的结构体字节对齐方式。
理解方式
将字节对齐分为两步:
- 对结构体内部进行对齐
- 结构体进行自对齐
首先是结构体内部进行对齐,假设有一个结构体如下所示:
typedef struct node{
char a;
short b;
char c;
}node;
内部对齐:内部对齐的方式是,前面的字段与后面的字段进行对齐。如:a 需要与 b 对齐,那么 a 需要扩充到 b 的整数倍,即 b/(a+扩充字节)=整数
,所以扩充字节数为 1(通常会扩充最少的字节达到目的,不会无意义地扩充很多字节)。同理,a+1+b
需要与 c 对齐,很显然,此时已经满足要求,即(a+1+b)/c=4
。所以结构体内部的字节数为 a+1+b+c = 5
字节。
结构体自对齐:结构体自对齐的意思是,结构体整体的大小需要是内部最长字段大小的整数倍。此处最长字段是 short b
,占 2 字节,那么结构体需要扩充 1 字节,使得 (内部字节数+扩充字节数)/内部最长字段字节数 = 整数
,即 (5 + 1)/2 = 3
。
因此,sizeof(node) 的大小应该是 6 字节。
练习的例子
typedef struct node{
char *a;
short b;
double c;
char d;
float e;
char f;
long g;
int h;
}node; // x86-64 指针占 8 字节,所以整体占用 56 字节
struct P1 { int i; char c; int j ; char d;}; // 16 字节
struct P2 { int i; char c; char d; long j;}; // 16 字节
struct P3 { short w[3]; char c[3];}; // 10 字节
struct P4 { short w[5]; char *c[3];}; // 40 字节
struct PS { struct P3 a[2]; struct P2 t;}; // 40 字节