各种数据类型的字节数
在32位计算机中,各种内置类型所占的字节数如下:
char-------------1bytes;
short------------2bytes;
int----------------4bytes;
long--------------4bytes;
float--------------4bytes;
double-----------8bytes;
long double----8bytes;
指针数据类型的sizeof
指针记录了另一个对象的地址,即指针变量是用来存放地址数据的,那么其当然等于计算机地址总线的宽度了。所以在32位计算机中,无论指针p指向何种类型的数据对象,其sizeof结果肯定为4bytes。
数组的sizeof值等于数组所占用的内存字节数。
char a1[]="abcd";
int a2[3];
sizeof(a1)=5*1=5bytes;//一个char类型占1byte
sizeof(a2)=3*4=12bytes;
结构体在内存中时如何实际存储的呢?
结构体的大小不是所有成员大小的简单的相加,还需要考虑一个很重要的问题---------系统在存储结构体变量时存在一个“边界对齐”的问题。其实,这是VC对变量存储的一个特殊处理。为了提高CPU的存储速度,VC对一些变量的起始地址做了“对齐”处理。在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。编译器会按照成员列表的顺序一个接一个地给每个成员分配内存的,字节对齐的细节遵循以下3个原则:
1)结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal padding);
2)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding);
这个就跟之前说到的__attribute__((packed))有关联了
//结构体1
struct Mystruct1
{
double data_db;
char data_ch;
int data_i;
};
分析:
为上面的结构体分配内存的时候,VC根据成员变量出现的顺序和对齐方式,先为第一个成员data_db分配内存,其起始地址跟结构的起始地址相同(即data_db的偏移量为0,刚好为sizeof(double)的倍数),该成员变量占用sizeof(double)=8个字节;接下来为第二个成员data_ch分配内存,这时下一个可以分配的地址相对于结构的起始地址的偏移量为8,是sizeof(char)的倍数,所以把data_ch存放在偏移量为8的地方满足对齐方式,该成员变量占用sizeof(char)=1个字节;接下来为第三个成员type分配空间,这时下一个可以分配的地址相对于结构的起始地址的偏移量为9,不是sizeof(int)=4的倍数,为了满足对齐方式对偏移量的约束问题,VC自动填充3个字节(这三个字节没有放什么东西),这时下一个可以分配的地址相对于结构的起始地址的偏移量为12,刚好是sizeof(int)=4的倍数,所以把type存放在偏移量为12的地方,该成员变量占用sizeof(int)=4个字节;这时整个结构的成员变量已经都分配了空间,总的占用的空间大小为:8+1+3+4=16,刚好为结构的字节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以没有空缺的字节需要填充。所以整个结构的大小为:sizeof(MyStruct)=8+1+3+4=16,其中有3个字节是VC自动填充的,没有放任何有意义的东西。
//结构体2
struct Mystruct2
{
char data_ch;
double data_db;
int data_i;
};
分析:
为上面的结构体分配内存的时候,VC根据成员变量出现的顺序和对齐方式,先为第一个成员data_ch分配内存,其起始地址跟结构的起始地址相同(即data_ch的偏移量为0,刚好为sizeof(char)的倍数),该成员变量占用sizeof(char)=1个字节;接下来为第二个成员data_db分配内存,这时下一个可以分配的地址相对于结构的起始地址的偏移量为1,不是sizeof(double)=8的倍数,为了满足对齐方式对偏移量的约束问题,VC自动填充7个字节(这7个字节没有放什么东西),这是下一个可以分配的地址相对于结构的起始地址的偏移量变为8,是sizeof(double)=8的倍数了,所以把data_db存放在偏移量为8的地方满足对齐方式,该成员变量占用sizeof(double)=8个字节。接下来为第三个成员data_i分配空间,这时下一个可以分配的地址相对于结构的起始地址的偏移量为16,是sizeof(int)=4的倍数,该成员变量占用sizeof(int)=4个字节;这时整个结构的成员变量已经都分配了空间,总的占用的空间大小为:1+7+8+4=20,不是结构的字节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以还得在第三个成员变量data_i的后面填充4个字节,使其达到24个字节,成为字节边界数的倍数。所以整个结构的大小为:sizeof(MyStruct)=1+7+8+4+4=24,其中有7+4个字节是VC自动填充的,没有放任何有意义的东西。