结构体是一些值的集合,这些值被称为成员变量,每个成员变量可以是不同类型的值。在计算结构体的大小时,应遵循结构体内存对齐的规则
1.1内存对齐的规则
1.第一个成员在与结构体变量偏移量为0的地址处。(偏移量是指该成员与结构体最开始开辟空间的地址的差值)
2.其他成员变量要对齐在对齐数的整数倍处,每个成员变量都有一个对齐数
(对齐数=编译器默认的一个对齐数与该成员变量的较小值 )
VS中默认对齐数为8
3.结构体总大小为最大对齐数的整数倍
4.若出现结构体嵌套的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体整体的大小为所有最大对齐数(包括嵌套的结构体的对齐数)的整数倍
1.2 为什么存在内存对齐
1.平台原因(移植原因)
不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件只能在某些地址处取特定类型的数据,否则硬件会出现异常
2.性能原因
数据结构(尤其是栈)应尽可能在自然边界上对齐
为了访问未对齐的数据,处理器需要做两次内存访问,而对齐的内存仅需要一次访问
结构体的内存对齐是一种用空间换取时间的做法
设计结构体时,为了减少空间的浪费,最好使占用空间少的成员集中在一起
1.3 修改默认对齐数
使用#pragma这个预处理指令,可以改变编译器的默认对齐数
#include<stdio.h>
#pragma pack(1)//设置默认对齐数为1
struct s2
{
char c1;
char c2;
int i;
}
#pragma pack()//取消设置的对齐数,还原为默认值
int main()
{
printf("%d\n", sizeof(struct s1));
return 0;
}
2.1 结构体实现位段
如果不考虑移植性,想要节省空间的话。可以用结构体实现位段
2.2 怎么声明位段
1.位段成员类型必须是int,unsigned int,或者char
2.位段成员名后面有一个冒号和一个数字
struct A
{
int _a : 2;
int _b : 5;
int _c : 10;
int _d : 30;
}
2.3 位段的内存分配
1.位段在空间上以一个字节(char)或四个字节(int)来开辟
2.位段涉及很多未被c语言标准规定的因素,因此位段是不跨平台的