面试常考,项目易错!C/C++中的字节对齐( 二 )


按照规则对齐 , 6字节是此结构体中最大数据类型 short 的整数倍 , 因此此结构体为6字节 , 后面的空白不需理会 , 可以实际编译一下运行 , 结果和分析一致为6个字节 。
double 的情况我们知道32位处理器一次只能处理32位也就是4个字节的数据 , 而 double 是8字节数据类型 , 这要怎么处理呢?
如果是64位处理器 , 8字节数据可以一次处理完毕 , 而在32位处理器下 , 为了也能处理 double8 字节数据 , 在处理的时候将会把 double 拆分成两个4字节数进行处理 , 从这里就会出现一种情况如下:
typedef struct test_32{ char a; char b; double c;}test_32; 这个结构体在32位下所占内存空间为12字节 , 只能拆分成两个4字节进行处理 , 所以这里规则对齐将判定该结构体最大数据类型长度为4字节 , 因此总长度为4字节的整数倍 , 也就是12字节 。
这个结构体在64位环境下所占内存空间为16字节 , 而64位判定最大为8字节 , 所以结果也是8字节的整数倍:16字节 。 这里的结构体中的double没有按照自然对齐放置到理论上的8字节倍数地址处 , 我认为这里编译器也有根据规则对齐做出相应的优化 , 节省了4个多余字节 。
这部分各位可以按照上述规则自行分析测试 。
数组对齐值为:min(数组元素类型 , 指定对齐长度) 。 但数组中的元素是连续存放 , 存放时还是按照数组实际的长度 。
如char t[9] , 对齐长度为1 , 实际占用连续的9byte 。 然后根据下一个元素的对齐长度决定在下一个元素之前填补多少byte 。
嵌套的结构体假设
struct A{ ...... struct B b; ......};对于B结构体在A中的对齐长度为:min(B结构体的对齐长度,指定的对齐长度) 。
B结构体的对齐长度为:上述2中结构整体对齐规则中的对齐长度 。 举个例子
//编译器://来源:技术让梦想更伟大//作者:李肖遥#include #include using namespace std;#pragma pack(8)struct Args{ char ch; double d; short st; char rs[9]; int i;} args;struct Argsa{ char ch; Args test; char jd[10]; int i;}arga;int main{ cout<<"Args:"< cout<<""<<(unsigned long) cout<<"Argsa:"< cout<<"Argsa:"<<(unsigned long) cout<<"Argsa:"<<(unsigned long) return 0;}输出结果:
面试常考,项目易错!C/C++中的字节对齐文章插图
改成#pragma pack (16)结果一样 , 这个例子证明了三点:

  • 对齐长度长于struct中的类型长度最长的值时,设置的对齐长度等于无用
  • 数组对齐的长度是按照数组成员类型长度来比对的
  • 嵌套的结构体中,所包含的结构体的对齐长度是结构体的对齐长度
指针主要是因为32位和64位机寻址上,来看看例子
//编译器://来源:技术让梦想更伟大//作者:李肖遥#include #include using namespace std;#pragma pack(4)struct Args{ int i; double d; char *p; char ch; int *pi;}args;int main{ cout<<"args length:"< cout<<"args1:"<<(unsigned long) cout<<"args2:"<<(unsigned long) return 0;}结果如下
pack48length3240args188args248
面试常考,项目易错!C/C++中的字节对齐文章插图
内存对齐的规则1、数据成员对齐规则
结构或联合的数据成员 , 第一个数据成员放在 offset 为0的地方 , 以后每个数据成员的对齐按照 #pragma pack 指定的数值和这个数据成员自身长度中 , 比较小的那个进行 。
例如 struct a里存有 struct b , b里有 char , int, double 等元素 , 那 b 应该从8的整数倍开始存储 。
2、结构体作为成员
如果一个结构里有某些结构体成员 , 则结构体成员要从其内部"最宽基本类型成员"的整数倍地址开始存储 。
在数据成员完成各自对齐之后 , 结构或联合本身也要进行对齐 , 对齐将按照#pragma pack 指定的数值和结构或联合最大数据成员长度中 , 比较小的那个进行 。