1. 为什么sizeof的结果和预期不符?
第一次用sizeof运算符时,很多人会惊讶地发现它返回的值和自己手算的不一样。我清楚地记得自己初学C语言时,给结构体成员累加字节数后,发现和sizeof的结果差了4个字节时的困惑。这种差异其实源于计算机系统中一些底层的内存对齐机制。
sizeof是C/C++中用来计算对象或类型所占内存大小的运算符。它返回的是编译器为该类型分配的实际内存字节数,而不是简单地把各成员大小相加。理解这个差异,需要从CPU访问内存的特性说起。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 内存对齐的底层原理
2.1 CPU访问内存的方式
现代CPU并不是以单个字节为单位访问内存的,而是以"字"(word)为单位。32位系统的字长通常是4字节,64位系统则是8字节。当CPU从内存读取数据时,如果数据地址正好对齐到字边界(即地址是字长的整数倍),读取效率最高。
举个例子,假设一个int变量在32位系统中存储在地址0x00000004(4的倍数),CPU可以一次读取整个int值。但如果它存储在0x00000003,就需要两次内存访问才能获取完整数据,这会显著降低性能。
2.2 对齐规则的具体表现
编译器为了保证这种高效访问,会在结构体成员之间插入填充字节(padding),使每个成员都满足其类型的对齐要求。基本数据类型的对齐要求通常是其自身大小:
- char: 1字节对齐
- short: 2字节对齐
- int: 4字节对齐
- double: 8字节对齐
结构体本身的对齐要求则等于其成员中最严格的那个。例如,包含double的结构体通常需要8字节对齐。
3. 结构体内存布局实例分析
3.1 简单结构体示例
c复制struct Example1 {
char a; // 1字节
int b; // 4字节
short c; // 2字节
};
如果简单相加,这个结构体应该是1+4+2=7字节。但在32位系统中,sizeof(Example1)实际返回12字节。这是因为编译器在成员之间插入了填充字节:
- a占用1字节(地址0)
- 插入3字节填充(地址1-3),使b从地址4开始(满足4字节对齐)
- b占用4字节(地址4-7)
- c占用2字
