#pragma pack

原文链接: http://www.cnblogs.com/s7vens/archive/2012/03/06/2382236.html

pack 为 struct, union 和 class 等的成员对齐指定字节边界. 与编译选项的 /Zp 开关不同, 它不针对整个项目, 而仅针对模块, 比如一个编译单元.

1. #pragma pack(show)
    以警告信息的形式显示当前字节对齐的值.
2. #pragma pack(n)
    将当前字节对齐值设为 n .
3. #pragma pack()
    将当前字节对齐值设为默认值(通常是8) .
4. #pragma pack(push)
    将当前字节对齐值压入编译栈栈顶.
5. #pragma pack(pop)
    将编译栈栈顶的字节对齐值弹出并设为当前值.
6. #pragma pack(push, n)
    先将当前字节对齐值压入编译栈栈顶, 然后再将 n 设为当前值.
7. #pragma pack(pop, n)
    将编译栈栈顶的字节对齐值弹出, 然后丢弃, 再将 n 设为当前值.
8. #pragma pack(push, identifier)
    将当前字节对齐值压入编译栈栈顶, 然后将栈中保存该值的位置标识为 identifier .
9. #pragma pack(pop, identifier)
    将编译栈栈中标识为 identifier 位置的值弹出, 并将其设为当前值. 注意, 如果栈中所标识的位置之上还有值, 那会先被弹出并丢弃.
10. #pragma pack(push, identifier, n)
    将当前字节对齐值压入编译栈栈顶, 然后将栈中保存该值的位置标识为 identifier, 再将 n 设为当前值.
11. #pragma pack(pop, identifier, n)
    将编译栈栈中标识为 identifier 位置的值弹出, 然后丢弃, 再将 n 设为当前值. 注意, 如果栈中所标识的位置之上还有值, 那会先被弹出并丢弃.
   
注意: 如果在栈中没有找到 pop 中的标识符, 则编译器忽略该指令, 而且不会弹出任何值.
   
// 代码段 1: 弹出编译栈的顺序跟压入的顺序相反
#pragma pack(show)      // 8 (默认值)
#pragma pack(push, 16) // 默认值 8 压入编译栈栈顶, 并将当前对齐值设为 16 .
#pragma pack(show)      // 上句设定的 16
#pragma pack(push, 4)   // 上上句 16 压入编译栈栈顶, 并将当前对齐值设为 4 .
#pragma pack(show)      // 上句设定的 4
#pragma pack(push, 2)   // 上上句 4 压入编译栈栈顶, 并将当前对齐值设为 2 .
#pragma pack(show)      // 上句设定的 2
#pragma pack(push, 1)   // 上上句 2 压入编译栈栈顶, 并将当前对齐值设为 1 .
#pragma pack(show)      // 上句设定的 1
#pragma pack(pop)         // 弹出编译栈栈顶的 2 , 并将其设为当前对齐值.
#pragma pack(show)      // 2
#pragma pack(pop)         // 弹出编译栈栈顶的 4 , 并将其设为当前对齐值.
#pragma pack(show)      // 4
#pragma pack(pop)         // 弹出编译栈栈顶的 16 , 并将其设为当前对齐值.
#pragma pack(show)      // 16
#pragma pack(pop)         // 弹出编译栈栈顶的 8 , 并将其设为当前对齐值.
#pragma pack(show)      // 8
 
// 代码段 2: pop 带有参数 n 时, 当前字节对齐值被设为了 n, 而不是从栈顶弹出的之前所压入的值.
#pragma pack(show)      // 8 (默认值)
#pragma pack(push, 16) // 默认值 8 压入编译栈栈顶, 并将当前对齐值设为 16 .
#pragma pack(show)      // 16
#pragma pack(push, 4)   // 上上句 16 压入编译栈栈顶, 并将当前对齐值设为 4 .
#pragma pack(show)      // 4
#pragma pack(push, 2)   // 上上句 4 压入编译栈栈顶, 并将当前对齐值设为 2 .
#pragma pack(show)      // 2
#pragma pack(push, 1)   // 上上句 2 压入编译栈栈顶, 并将当前对齐值设为 1 .
#pragma pack(show)      // 1
#pragma pack(pop, 8)     // 弹出编译栈栈顶的 2 , 然后丢弃, 再将当前对齐值设为 8 .
#pragma pack(show)      // 8
#pragma pack(pop, 1)     // 弹出编译栈栈顶的 4 , 然后丢弃, 再将当前对齐值设为 1 .
#pragma pack(show)      // 1
#pragma pack(pop, 2)     // 弹出编译栈栈顶的 16 , 然后丢弃, 再将当前对齐值设为 2 .
#pragma pack(show)      // 2
#pragma pack(pop, 16)   // 弹出编译栈栈顶的 8 , 然后丢弃, 再将当前对齐值设为 16 .
#pragma pack(show)      // 16
 
// 代码段3: push 和 pop 可以带有标识符, 此标识符能够弹出指定值. 但是, 位于栈中指定值之上的那些值均会被弹出并丢弃. 
#pragma pack(show)                          // 8 (默认值)
#pragma pack(push, identifier_1, 1)   // 默认值 8 压入编译栈栈顶, 并将栈中 8 对应的位置用 identifier_1 标识起来, 然后将当前对齐值设为 1 .
#pragma pack(show)                          // 1
#pragma pack(push, identifier_2, 2)   // 上上句 1 压入编译栈栈顶, 并将栈中 1 对应的位置用 identifier_2 标识起来, 然后将当前对齐值设为 2 .
#pragma pack(show)                          // 2
#pragma pack(push, identifier_3, 4)   // 上上句 2 压入编译栈栈顶, 并将栈中 2 对应的位置用 identifier_3 标识起来, 然后将当前对齐值设为 4 .
#pragma pack(show)                          // 4
#pragma pack(push, identifier_4, 8)   // 上上句 4 压入编译栈栈顶, 并将栈中 4 对应的位置用 identifier_4 标识起来, 然后将当前对齐值设为 8 .
#pragma pack(show)                          // 8
#pragma pack(push, identifier_5, 16) // 上上句 8 压入编译栈栈顶, 并将栈中 8 对应的位置用 identifier_5 标识起来, 然后将当前对齐值设为 16 .
#pragma pack(show)                          // 16
#pragma pack(push, identifier_6)       // 上上句 16 压入编译栈栈顶, 并将栈中 16 对应的位置用 identifier_6 标识起来.
#pragma pack(show)                          // 16
#pragma pack(pop, identifier_6)         // 将标识符 identifier_6 对应的栈中值 16 弹出, 并将其设为当前对齐值.
#pragma pack(show)                          // 16
#pragma pack(pop, identifier_5, 2)     // 将标识符 identifier_6 对应的栈中值 8 弹出, 然后丢弃, 再将当前对齐值设为 2 .
#pragma pack(show)                          // 2
#pragma pack(pop, identifier_1)         // 按入栈顺序进行弹出, 直到遇到标识符 identifier_1 标识的8 .
#pragma pack(show)                          // 8

时间: 2024-10-13 10:37:03

#pragma pack的相关文章

C语言字节对齐 __align(),__attribute((aligned (n))),#pragma pack(n)

转载地址 : http://blog.csdn.net/21aspnet/article/details/6729724 一.概念    对齐跟数据在内存中的位置有关.如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐.比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的.   二.为什么要字节对齐   需要字节对齐的根本原因在于CPU访问数据的效率问题.假设上面整型变量的地址不是自然对齐,比如为0x00000002,则CPU如果取它的值的话需要访

C/C++中的内存对齐问题和pragma pack命令详解

这个内存对齐问题,居然影响到了sizeof(struct)的结果值.突然想到了之前写的一个API库里,有个API是向后台服务程序发送socket请求.其中的socket数据包是一个结构体.在发送socket之前,会检测数据的长度:服务端接收到数据后也会检测长度.如果说内存对齐问题影响到了结构体的sizeof,那么socket发送结构体的时候,是怎么发送的?发送的内容中是否包含结构体中的“空洞”?如果API库中的对齐方式没有设定,那么服务端和客户端的sizeof结果将不同,这会引起很多问题吗? 下

#pragma pack(push,1)与#pragma pack(pop)

这是给编译器用的参数设置,有关结构体字节对齐方式设置, #pragma pack是指定数据在内存中的对齐方式. #pragma pack (n)             作用:C编译器将按照n个字节对齐.#pragma pack ()               作用:取消自定义字节对齐方式. #pragma  pack (push,1)     作用:是指把原来对齐方式设置压栈,并设新的对齐方式设置为一个字节对齐 #pragma pack(pop)            作用:恢复对齐状态 因

关于结构体占用空间大小总结(#pragma pack的使用)

关于C/C++中结构体变量占用内存大小的问题,之前一直以为把这个问题搞清楚了,今天看到一道题,发现之前的想法完全是错误的.这道题是这样的: 在32位机器上,下面的代码中 class A { public: int i; union U { char buff[13]; int i; }u; void foo(){} typedef char* (*f)(void*); enum{red , green, blue}color; }a; sizeof(a)的值是多少?如果在代码前面加上#pragm

#pragma pack(n) 的宏实现

老样子,上代码,上公式 #ifndef ALIGNED #define ALIGNED(T, A, B) (((A) + (B) - 1) & (~((T)(B) - 1))) #endif 在VC 平台上 我们会这样让内存对其 #pragma pack(n) /* n = 1, 2, 4, 8, 16 */ 如果我们写这样一个程序,该如何实现呢? 这里先上一个例子:例如 7, 以4 对齐, 我们知道对齐后的大小是比7大的4的最小的整数倍. 4的二进制是0100, 减一取反 ~(0100-000

#pragma pack(push) 和#pragma pack(pop) 以及#pragma pack()

我们知道结构体内存对齐字节可以通过#pragma pack(n) 的方式来指定. 但是,有没有想过一个问题,某些时候我想4字节对齐,有些时候我又想1字节或者8字节对齐,那么怎么解决这个问题呢? 此时,#pragma pack(push) 和#pragma pack(pop) 以及#pragma pack()应运而生. 看测试代码:(说明,64位GCC,默认8字节对齐) 屏蔽了的代码选别看,只看这个结构体,在默认8字节对齐的方式下,sizeof大小为24个字节,这不再做分析,之前随笔分析过了. 然

#Pragma Pack(n)与内存分配

#pragma pack(n) 解释一: 每个特定平台上的编译器都有自己的默认"对齐系数"(也叫对齐模数).程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的"对齐系数". 规则: 1.数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进

C++/CLI 托管C++之结构体封装(内存对齐#pragma pack)【9】

CLI封装涉及内存对齐的结构体时,使用的是StructLayoutAttribute,指定Pack为1.4.8等属性. [1]C++导出函数,使用 1位对齐 #pragma pack(push) #pragma pack(1) typedef struct _testStru2 { int iVal; char cVal; __int64 llVal; }testStru2; #pragma pack(pop) //4.2 结构体边界对齐 EXPORTDLL_CLASS void Struct_

warning: malformed '#pragma pack(pop[, id])' - ignored

关于这个警告信息,就是说忽略了我定义的结构体对齐信息,那么他就会按照默认的对齐来了.运行结果自然也是有错误的. 经过测试对比,发现是gcc版本问题,我的ubuntu中,gcc版本为4.4.1,还算比较新的.而交叉编译工具链中arm-linux-gcc中的gcc版本为3.4.5,比较老了. 查找了一些资料,发现使用 _attribute_((packed)) 可以解决这个问题,_attribute_((packed)) 的作用是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,

#pragma pack(push,1)与#pragma pack(1)的区别(转)

这是给编译器用的参数设置,有关结构体字节对齐方式设置, #pragma pack是指定数据在内存中的对齐方式. #pragma pack (n)             作用:C编译器将按照n个字节对齐.#pragma pack ()               作用:取消自定义字节对齐方式. #pragma  pack (push,1)     作用:是指把原来对齐方式设置压栈,并设新的对齐方式设置为一个字节对齐 #pragma pack(pop)            作用:恢复对齐状态 因