sizeof全面总结——举一反三详细介绍sizeof(结构体)

  • Post author:
  • Post category:其他

字节

short

int

float

long

*(地址)

double

long long

32位

2

4

4

4

4

8

8

64位

2

4

4

8

8

8

8

         *有无unsigned修饰都一样

  • 编译器pack指令 #pragma pack(n)——定义n字节对齐
  • C++固有类型的对齐取编译器对齐与自身大小中较小的一个
  • 32位C++默认8字节对齐。gcc编译器默认4字节对齐
  • static变量在静态区,sizeof均不纳入计算
  • 在编译阶段处理,sizeof作用范围内的内容不能被编译,所以sizeof()内的运算不被执行
  • sizeof(函数)=sizeof(返回值类型)
  • sizeof和strlen:sizeof计算字符串容量,算’\0’,strlen计算字符串长度,到’\0’截止
  1. 类:非static数据成员变量+虚函数指针+对齐;无论多少个虚函数,都只有一个指向虚函数表的指针(4字节)
  2. 联合体:最长成员的大小对齐
  3. 带位域:相邻位域字段的两个变量若类型相同,当两个字段位宽和小于此类型大小时,二者紧邻存储;若二者位宽和大于本类型大小,则第二个字段从新存储单元开始,偏移量为其类型大小整数倍。若相邻位域字段类型不同,则视编译器决定是否压缩存储,VC6不压缩,Dec-C++压缩。如果位域字段穿插着非位域字段,不压缩。
  4. 数组:数组占内存字节=元素个数*元素长度; 当数组作为函数参数传递时,蜕变成指针
double* (*a)[3][6];
cout<<sizeof(a)<<endl; // 4
cout<<sizeof(*a)<<endl; // 72
cout<<sizeof(**a)<<endl; // 24
cout<<sizeof(***a)<<endl; // 4
cout<<sizeof(****a)<<endl; // 8
  • a是一个很奇怪的定义,他表示一个指向 double*[3][6]类型数组的指针。既然是指针,所以sizeof(a)就是4。
  • *a就表示一个元素为double*、大小为[3][6]的多维数组类型,因此sizeof(*a)=3*6*sizeof(double*)=72。
  • **a表示一个double*[6]类型的数组,所以sizeof(**a)=6*sizeof(double*)=24。
  • ***a就表示其中的一个元素,也就是double*了,所以sizeof(***a)=4。
  • ****a,就是一个double了,所以sizeof(****a)=sizeof(double)=8。

5、结构体(编译器考虑默认8字节对齐的情况下):

  •  结构体变量的首地址能够被其最宽基本类型成员的大小所整除;(这条在结构体作为结构体成员时考察)
  • 结构体每个成员相对于结构体首地址的偏移量(offset)都是此成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
  • 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。

由于结构体的成员可以是复合类型,比如另外一个结构体,所以在寻找最宽基本类型成员时,应当包括复合类型成员的子成员,而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。

举例理解:

S3中最长成员时,将S1打散,找S1S3中所有基础变量最长的,以其长度为S3对齐字节数:int 4

确定S3对齐字节数后,挨个放置S3成员变量时,将S1看作一个整体(8字节复合变量)一次性存放,并且S1的对齐方式为其自身对齐字节数(4字节对齐。S1也是结构体,有自己的对齐字节数,计算偏移量时按照自己的对齐字节数计算)

实验验证正确:

    

sizeof(s)=32

取结构体S5变量地址,看各个成员在内存中的存放情况:

  • 左边是地址,右边是十六进制表示的成员ASCII值,cc是补齐字节
  • 值0x61:’a’,占一个字节
  • 0x62、0x01-0x00:’b’、1,共占8个字节(s1当作一个整体,自身对齐字节数4,即开始存放的地址对结构体首地址偏移量为4的倍数,故补齐3个字节)
  • 0x31-0x00:”12345”,共占6字节,含’\0’,(s2对结构体首地址偏移量1字节倍数,即紧邻s1)
  • 0x00-0x40:2.0,共占8字节(因为前面加起来刚好18字节,double为8字节对齐,对结构体首地址的偏移为8的倍数,故补齐了6个字节)

举一反三:

     

sizeof(s)=32;

  • c1占1字节——1
  • s1对齐4,占8字节——1+3+8=12
  • s2对齐8,占16字节——12+4+16=32

当然了:

如果S5再加个短于double的变量中double后面,如char或int,则会因为结构体大小要为最长成员整数倍而补齐成40字节(已经实验验证)

最后:

sizeof(结构体) 还和编译器有关,取二者较小


版权声明:本文为EVEcho原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。