昨天写了一个结构体demo,心血来潮打印struct所占内存字节数
struct student{
char name[20];
char sex;
int num;
float score[3];
void print();
};
你猜猜是多少个字节数呢(对于char[]这样的赋值,先暂且不提)
struct student stu1 = {"Bob",'M',001,100,100,100};
cout<< sizeof(stu1 )<<endl;
sizeof(stu1):40
没想到吧。多出来的3个字节是哪里的。
struct student{
char name[20];//开辟3个8位,char[20],占20位,还剩4位
char sex;//char占4位中的1位
int num;//剩下的3位,无法满足长度,新开一个8位,占4位
float score[3];//剩下4位,float 占4位,3个float占12位,再开一个8位,刚好24+8+8=40
void print();
};
实际上第二个char型成员虽然本来只有1个字节,但实际上却占用掉了4个字节,因为结构体中空间最大的类型是int,所以整个结构体按4字节对齐。
如果换成是double,结构体中空间最大的类型是double,整个结构体按8字节对齐。
struct student{
char name[20];//开辟3个8位,char[20],占20位,还剩4位
char sex;//char占4位中的1位
int num;//剩下的3位,无法满足长度,新开一个8位,占4位
double score[3];//剩下4位无法满足长度,double占8位,再开3个8位,刚好24+8+24=56
void print();
};
sizeof(stu1):56
而#pragma pack(1)让编译器将结构体数据强制连续排列。结果就是37。
#pragma pack(1)//强制1字节对齐,也就是连续排列
struct student{
char name[20];
char sex;
int num;
float score[3];
void print();
};
sizeof(stu1):37
我们再来看一个实例
typedef struct{
int x5; //开辟第1个8位,占据前4位
double x6;//剩下4位无法满足,开辟第2个8位,刚好用完
char x7;//开辟第3个8位,占据1位。其余为对齐占位,总计3*8=24位
}x;
sizeof(x):24
我们把char移到前面的位置去,结果又不一样。
typedef struct{
char x7;//开辟第1个8位,占据1位
int x5; //剩下7位,int占据4位
double x6;//剩下3位无法满足,开辟第2个8位,刚好用完.
}x;
sizeof(x):16
typedef struct{
char x7;//开辟第1个8位,占据1位
int x5; //剩下7位,int占据4位
float x6;//剩下3位无法满足,开辟第2个8位,只要用掉4位就好,因为这个结构体最大类型是占4个字节.所以结果是12
}x;
sizeof(x):12
相信看完这几个实例,你已经对结构体占内存字节数已有所了解。
总结:
结构体中数据所占字节会按最大的类型所占内存字节对齐。可以使用#pragma pack(1)让编译器将结构体数据强制连续排列,#pragma pack(n)想让它按几个字节排列都可以。
我们再来看一个实例
typedef struct X{
int i1,i2,i3,i4,i5;
struct X *next;
}*pX;
int main(void)
{
pX p_new = NULL;
cout<< sizeof(p_new->next)<<endl;
cout<< sizeof(pX)<<endl;
cout<< sizeof(X)<<endl;
return 0;
}
结果是:
8
8
32
指针占用内存字节数是8,因为我电脑是64位。如果是在32位系统中,指针是占用4个字节的。
前面5个int型数据,占用20个字节,3个8位,一共24个位,剩下4个位,无法满足指针占用的长度,需要按照struct最大类型8字节对齐,所以是再开一个8位,也就是一起32位。如果代码前面规定#pragma pack(4),这个时候,结果就是28位了。