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


3、1

  • 语法
#pragma pack( [show] | [push | pop] [, identifier], n )
  • 说明
  1. pack提供数据声明级别的控制 , 对定义不起作用;
  2. 调用pack时不指定参数 , n将被设成默认值;
  3. 一旦改变数据类型的 alignment , 直接效果就是占用 memory 的减少 , 但是 performance 会下降;
  • 语法具体分析
  1. show:可选参数
显示当前 packing aligment 的字节数 , 以 warning message 的形式被显示;
  1. push:可选参数
将当前指定的 packing alignment 数值进行压栈操作 , 这里的栈是 the internal compiler stack , 同时设置当前的 packing alignment 为n;如果n没有指定 , 则将当前的 packing alignment 数值压栈;
  1. 【面试常考,项目易错!C/C++中的字节对齐】pop:可选参数
从 internal compiler stack 中删除最顶端的record;如果没有指定n , 则当前栈顶 record 即为新的 packing alignment 数值;如果指定了n , 则n将成为新的 packing aligment 数值;如果指定了 identifier , 则 internal compiler stack 中的 record 都将被 pop 直到 identifier 被找到 , 然后 pop出 identitier , 同时设置 packing alignment 数值为当前栈顶的 record;如果指定的 identifier 并不存在于 internal compiler stack , 则 pop 操作被忽略;
  1. identifier:可选参数
当同 push 一起使用时 , 赋予当前被压入栈中的 record 一个名称;当同 pop一起使用时 , 从 internal compiler stack 中 pop 出所有的 record 直到identifier 被 pop 出 , 如果 identifier 没有被找到 , 则忽略 pop 操作;
  1. n:可选参数
指定packing的数值 , 以字节为单位;缺省数值是8 , 合法的数值分别是1、2、4、8、16
例子#include#includeusing namespace std;#pragma pack(4)struct m { int a; short b; int c;};int main{ cout <<"结构体m的大小:"<< sizeof(m) << endl; cout << endl; // 获得成员a相对于m储存地址的偏移量 int offset_b = offsetof(struct m, a); cout <<"a相对于m储存地址的偏移量:"<< offset_b << endl; system("pause"); return 0;}
面试常考,项目易错!C/C++中的字节对齐文章插图
从运行结果来看我们可以证实上面内存对齐规则的第一条:第一个数据成员放在offset为0的地方 。
现在咱来看看上面结构体是如何内存对齐的;先用代码打印它们每个数据成员的存储地址的偏移量
//编译器://来源:技术让梦想更伟大//作者:李肖遥#include#includeusing namespace std;#pragma pack(4)struct m { int a; short b; int c;};int main{ cout <<"结构体m的大小:"<< sizeof(m) << endl; cout << endl; int offset_b = offsetof(struct m, a);// 获得成员a相对于m储存地址的偏移量 int offset_b1 = offsetof(struct m, b);// 获得成员a相对于m储存地址的偏移量 int offset_b2 = offsetof(struct m, c);// 获得成员a相对于m储存地址的偏移量 cout <<"a相对于m储存地址的偏移量:"<< offset_b << endl; cout << "b相对于m储存地址的偏移量:" << offset_b1 << endl; cout << "c相对于m储存地址的偏移量:" << offset_b2 << endl; //system("pause"); return 0;}
面试常考,项目易错!C/C++中的字节对齐文章插图
在此c在结构体中偏移量为8加上它自身(int)4个字节 , 刚好是12(c的开始位置为8 , 所以要加它的4个字节)
上面内存结束为11 , 因为0-11 , 12是最大对齐数的整数倍 , 故取其临近的倍数 , 所以就取4的整数倍即12;
上图中我用连续的数组来模仿内存 , 如图是它们的内存对齐图;
如果将最大内存对齐数改为8 , 他将验证内存对齐规则中的第3条 。
如果将其改为2 , 会发生什么:我们来看看:
//编译器://来源:技术让梦想更伟大//作者:李肖遥#include#includeusing namespace std;#pragma pack(2)struct m { int a; short b; int c;};int main{