应该是 5。是这样吗你在你机器上试过了吗也许你是对的,但很可能你是错的!VC6 中按默认设置得到的
结果为 8。
Why 为什么受伤的总是我
请不要沮丧,我们来好好琢磨一下 sizeof 的定义——sizeof 的结果等于对象或者类型所占的内
存字节数,好吧,那就让我们来看看 S1 的内存分配情况:
S1 s1 = { 'a', 0xFFFFFFFF };
定义上面的变量后,加上断点,运行程序,观察 s1 所在的内存,你发现了什么
以我的 VC6.0 为例,s1 的地址为 0x0012FF78,其数据内容如下:
0012FF78: 61 CC CC CC FF FF FF FF
发现了什么怎么中间夹杂了 3 个字节的 CC 看看 MSDN 上的说明:
When applied to a structure type or variable, sizeof returns the actual size, which may include
padding bytes inserted for alignment.
原来如此,这就是传说中的字节对齐啊!一个重要的话题出现了。
为什么需要字节对齐计算机组成原理教导我们这样有助于加快计算机的取数速度,否则就得多
花指令周期了。为此,编译器默认会对结构体进行处理(实际上其它地方的数据变量也是如此),让宽度
为 2 的基本数据类型(short 等)都位于能被 2 整除的地址上,让宽度为 4 的基本数据类型(int 等)都位
于能被 4 整除的地址上,以此类推。这样,两个数中间就可能需要加入填充字节,所以整个结构体的
sizeof 值就增长了。
让我们交换一下 S1 中 char 与 int 的位置:
struct S2
{
int i;
char c;
};
看看 sizeof(S2)的结果为多少,怎么还是 8 再看看内存,原来成员 c 后面仍然有 3 个填充字节,
这又是为什么啊别着急,下面总结规律。
字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编
译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成
员之后加上填充字节(trailing padding)。