各个类型的sizeof()取值

转载自:EVEcho  
 

一般类型

测试代码:

#include 
using namespace std;

int main() {
	short a = 0;
	cout << sizeof(a) << endl;			//2
	int b = 0;
	cout << sizeof(b) << endl;			//4
	float c = 0.00;
	cout << sizeof(c) << endl;			//4
	long d = 0;
	cout << sizeof(d) << endl;			//4
	double e = 0.0;
	cout << sizeof(e) << endl;			//8
	long long f = 0;		
	cout << sizeof(f) << endl;			//8
	int* g = &b;
	cout << sizeof(g) << endl;			//8
	

	int* (*h)[3][6];
	cout << sizeof(h) << endl;		     //8    int指针(指向(*h)[3][6]):8
	cout << sizeof(*h) << endl;			 //144	二维指针数组(元素类型int*):3*6*8
	cout << sizeof(**h) << endl;		 //48	指针数组(元素类型int*[6]):6*8
	cout << sizeof(***h) << endl;		 //8    数组内元素(int*):8
	cout << sizeof(****h) << endl;		 //4	int:4

}

字节表

字节 short int float long double long long *(地址)
32位 2 4 4 4 8 8 4
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. 数组:数组占内存字节=元素个数*元素长度; 当数组作为函数参数传递时,蜕变成指针
     

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

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

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

#include 
using namespace std;

struct S1 {
	char c1;
	int i;
};

struct S2 {
	char s2[6];
};

struct S3 {
	char c1[6];
	int i;
	S1 s1;
};

struct S4 {
	char c1;
	S1 s1;
	S2 s2;
	double d;
};

void test() {
	cout << sizeof(S1) << endl;		//8
	cout << sizeof(S2) << endl;		//6
	cout << sizeof(S3) << endl;		//20
	S4 s = { 'a','b',1,"12345",2.0 };
	cout << sizeof(S4) << endl;		//32
}


int main() {

	test();
}

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

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

实验验证正确~sizeof(s)=32

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

各个类型的sizeof()取值_第1张图片

  • 左边是地址,右边是十六进制表示的成员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()取值_第2张图片

 

c1占1字节——1
s1对齐4,占8字节——1+3+8=12
s2对齐8,占16字节——12+4+16=32
当然了:

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

最后:

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

你可能感兴趣的:(C/C++)