c/c++编译器的缺省字节对齐方式为自然对界。 即在缺省情况下,编译器为每一个变量或是数据单元按其自然对界条件分配空间。
在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间。 各个成员按照它们被声明的顺序在内存中顺序存储(成员之间可能有插入的空字节),第一个成员的地址和整个结构的地址相同。
编译器缺省的结构成员自然对界条件为“n字节对齐”,n即该成员数据类型的长度。 如int型成员的自然对界条件为4字节对齐,而double类型的结构成员的自然对界条件为8字节对齐。 若该成员的起始偏移不位于该成员的“默认自然对界条件”上,则在前一个节面后面添加适当个数的空字节。
编译器缺省的结构整体的自然对界条件为:该结构所有成员中要求的最大自然对界条件。 若结构体各成员长度之和不为“结构整体自然对界条件的整数倍”,则在最后一个成员后填充空字节。
例子1(分析结构各成员的默认字节对界条界条件和结构整体的默认字节对界条件):
struct test{ char x1; // 成员x1为char型(其起始地址必须1字节对界),其偏移地址为0 char x2; // 成员x2为char型(其起始地址必须1字节对界,其偏移地址为1 float x3; // 成员x3为float型(其起始地址必须4字节对界),编译器在x2和x3之间填充了两个空字节,其偏移地址为4 char x4; // 成员x4为char型(其起始地址必须1字节对界),其偏移地址为8 };在test结构体中,最大的成员为float x3,因此结构体的自然对界条件为4字节对齐。 则结构体长度就为12字节,内存布局为1100 1111 1000。
例子2:
#include typedef struct{ int aa1; //4个字节对齐 1111 char bb1;//1个字节对齐 1 short cc1;//2个字节对齐 011 char dd1; //1个字节对齐 1} testlength1;int length1 = sizeof(testlength1); //4个字节对齐,占用字节1111 1011 1000,length = 12typedef struct{ char bb2;//1个字节对齐 1 int aa2; //4个字节对齐 01111 short cc2;//2个字节对齐 11 char dd2; //1个字节对齐 1} testlength2;int length2 = sizeof(testlength2); //4个字节对齐,占用字节1011 1111 1000,length = 12typedef struct{ char bb3; //1个字节对齐 1 char dd3; //1个字节对齐 1 int aa3; //4个字节对齐 001111 short cc23//2个字节对齐 11} testlength3;int length3 = sizeof(testlength3); //4个字节对齐,占用字节1100 1111 1100,length = 12typedef struct{ char bb4; //1个字节对齐 1 char dd4; //1个字节对齐 1 short cc4;//2个字节对齐 11 int aa4; //4个字节对齐 1111} testlength4;int length4 = sizeof(testlength4); //4个字节对齐,占用字节1111 1111,length = 8int main(void){ printf(length1 = %d.\\n,length1); printf(length2 = %d.\\n,length2); printf(length3 = %d.\\n,length3); printf(length4 = %d.\\n,length4); return 0;}改变缺省的对界条件(指定对界)
· 使用伪指令#pragma pack (n),编译器将按照n个字节对齐。
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。
这时,对齐规则为:
1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
结合1、2推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。
因此,当使用伪指令#pragma pack (2)时,test结构体的大小为8,内存布局为11 11 11 10。
需要注意一点,当结构体中包含一个子结构体时,子结构中的成员按照#pragma pack指定的数值和子结构最大数据成员长度中,比较小的那个进行进行对齐。 例子如下:
#pragma pack(8)struct s1{ short a; long b;};struct s2{ char c; s1 d; long long e;};#pragma pack()sizeof(s2)的结果为24。 s1的内存布局为1100 1111,s2的内存布局为1000 1100 1111 0000 1111 1111。
例子2按照2个字节对齐时:
#include #pragma pack(2)typedef struct{ int aa1; //2个字节对齐 1111 char bb1;//1个字节对齐 1 short cc1;//2个字节对齐 011 char dd1; //1个字节对齐 1} testlength1;int length1 = sizeof(testlength1); //2个字节对齐,占用字节11 11 10 11 10,length = 10typedef struct{ char bb2;//1个字节对齐 1 int aa2; //2个字节对齐 01111 short cc2;//2个字节对齐 11 char dd2; //1个字节对齐 1} testlength2;int length2 = sizeof(testlength2); //2个字节对齐,占用字节10 11 11 11 10,length = 10typedef struct{ char bb3; //1个字节对齐 1 char dd3; //1个字节对齐 1 int aa3; //2个字节对齐 11 11 short cc23//2个字节对齐 11} testlength3;int length3 = sizeof(testlength3); //2个字节对齐,占用字节11 11 11 11,length = 8typedef struct{ char bb4; //1个字节对齐 1 char dd4; //1个字节对齐 1 short cc4;//2个字节对齐 11 int aa4; //2个字节对齐 11 11} testlength4;int length4 = sizeof(testlength4); //2个字节对齐,占用字节11 11 11 11,length = 8#pragma pack()int main(void){ printf(length1 = %d.\\n,length1); printf(length2 = %d.\\n,length2); printf(length3 = %d.\\n,length3); printf(length4 = %d.\\n,length4); return 0;}另外,还有如下的一种方式:
· __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。 如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
· attribute ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。
以上的n = 1, 2, 4, 8, 16... 第一种方式较为常见。
光纤端口连接交换机需要注意的要求
选择电缆连接器组件时周围环境的注意事项
Apple Keynote推出iPhone X和FaceID
售电公司如何控制偏差考核?变电站运维云平台——安科瑞 严新亚
哪款二维码扫码模块适合嵌入智能快递柜?二维码扫描模组模块推荐
C/C++编译器的缺省字节对齐方式
三款常见的家用发动机型号盘点
VR转接器:打破界限,畅享虚拟现实
智能穿戴设备以优越的性能在市场上占据了主流
立式广告机成为广告信息的流行展现形式
区块链数字宠物游戏“熊猫环球”8大优势引领区块链宠物游戏新高度
广汽埃安与华为合作生变!项目改为自主开发,车企欲掌握核心技术话语权?
大彩串口屏新品发布:爆款7寸HMI外壳串口屏开窗尺寸192*138
工业互联网的现实应用场景及其关键典型技术
如何运用正确方法管理攻击面
后补贴时代,磷酸铁锂电池强势回归
什么是数据结构
NVIDIA Isaac Sim 2022.1版本的亮点及功能
一文了解RISC-V
66W极速回血,华为Mate 40系列快充技术终追上潮流