sizeof的结果(以下结果都是在Linux v2.6 gcc v4获取)
sizeof操作符的结果类型是size_t
sizeof操作符的结果类型是size_t
1、ANSI C正式规定字符类型为1字节。
2、其他类型在ANSI C中没有具体规定,大小依赖于实现。
3、当操作数是指针时,sizeof依赖于编译器。
4、当操作数具有数组类型时,其结果是数组的总字节数。
6、当操作数是联合类型时,sizeof是其最大字节成员的字节数。
结构体
sizeof()对结构体指针求值时,注意需对齐;
struct a{ //对struct来说
在Linux上: sizeof(a) = 12;
这是因为编译器在考虑对齐问题时,在结构中插入空位以控制各成员对象的地址对齐。
因为对齐问题使结构体的sizeof变得比较复杂,看下面的例子:(默认对齐方式下)
struct s1 { char a; double b; int c; char d; }; struct s2 { char a; char b; int c; double d; }; cout << sizeof (s1) << endl; // 24 cout << sizeof (s2) << endl; // 16
同样是两个char类型,一个int类型,一个double类型,但是因为对界问题,导致他们的大小不同。计算结构体大小可以采用元素摆放法,我举例子说明一下:首先,CPU判断结构体的对界,s1和s2的对界都取最大的元素类型,也就是double类型的对界8。然后开始摆放每个元素。
对于s1,首先把a放到8的对界,假定是0,此时下一个空闲的地址是1,但是下一个元素d是double类型,要放到8的对界上,离1最接近的地址是8了,所以d被放在了8,此时下一个空闲地址变成了16,下一个元素c的对界是4,16可以满足,所以c放在了16,此时下一个空闲地址变成了20,下一个元素d需要对界1,也正好落在对界上,所以d放在了20,结构体在地址21处结束。由于s1的大小需要是8的倍数,所以21-23的空间被保留,s1的大小变成了24。
对于s2,首先把a放到8的对界,假定是0,此时下一个空闲地址是1,下一个元素的对界也是1,所以b摆放在1,下一个空闲地址变成了2;下一个元素c的对界是4,所以取离2最近的地址4摆放c,下一个空闲地址变成了8,下一个元素d的对界是8,所以d摆放在8,所有元素摆放完毕,结构体在15处结束,占用总空间为16,正好是8的倍数。
这里有个陷阱,对于结构体中的结构体成员,不要认为它的对齐方式就是他的大小,看下面的例子:
struct s1 { char a[ 8 ]; }; struct s2 { double d; }; struct s3 { s1 s; char a; }; struct s4 { s2 s; char a; }; cout << sizeof (s1) << endl; // 8 cout << sizeof (s2) << endl; // 8 cout << sizeof (s3) << endl; // 9 cout << sizeof (s4) << endl; // 16
s1和s2大小虽然都是8,但是s1的对齐方式是1,s2是8(double),所以在s3和s4中才有这样的差异。所以,在自己定义结构体的时候,如果空间紧张的话,最好考虑对齐因素来排列结构体里的元素。
32位和64位下结构体内存对齐问题:
struct A
{
int a;
char b;
double c;
char d;
};
struct B
{
char a;
double b;
char c;
};
64位时按照8字节对齐
structA: 4+(1+3)+8+(1+7) = 24
structB: (1+7)+8+(1+7) = 24
计算结果与输出是一样的。
这两个结构体在内存中存储应该是下面这样的:
struct A: 整体按照8字节(double长度)对齐
struct B :
32位时按照4字节对齐
结果和64位下完全不一样,很显然它没有按照最长成员double的8字节对齐。稍微想一下就明白了,因为32位只有4个字节,最长对齐模数只能按4个字节来对齐,double 是分成了2个4字节。上面两个结构体在内存中应该是这种形式。
struct A:整体按照4字节对齐
4+(1+3)+8+(1+3) = 20
struct B :
(1+3)+8+(1+3) = 16
内存空间实际上是连续的,上面分块的画法只是为了方便理解。
union u{ //对union来说
关于内存对齐的介绍
http://blog.csdn.net/csw_100/article/details/5495309