#pragma pack()用法

作者: hplllrhp | 来源:发表于2019-01-03 11:56 被阅读0次

在阅读代码特别是C语法代码的过程中,其实经常会遇到#pragma pack(n),#pragma pack(),#pragma pack(pack,n),#pragma pack(pop,n)等,其中n是可以省略的。
并且这些语句一般出现在结构体前面。我们一般都知道该语句是用来进行内存对齐的,但是总结得不是特别清晰。
我在查阅博客的过程中,找到了一个总结得比较好的帖子,然后补充一点我自己的情况。

以下是原博客内容(#pragma pack 指令详解!):

#pragma pack这个指令和他涉及的c/c++内存对齐机制可能是技术开发类笔试面试被问道的最频繁的问题之一了
,可惜笔者在实际生活中发现大量的工程人员乃至面试官自身对于这个预处理指令都是一知半解,所以今天在简
书为大家详细讲解一下这个指令。

1.#pragma简述:

在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。 今天为大家说的就是其中的#pragma pack指令。

2.#pragma pack的作用:

这个其实点进这个帖子的人都懂,#pragma pack 的主要作用就是改变编译器的内存对齐方式,这个指令在网络报文的处理中有着重要的作用,#pragma pack(n)是他最基本的用法,其作用是改变编译器的对齐方式, 不使用这条指令的情况下,编译器默认采取#pragma pack(8)也就是8字节的默认对齐方式,n值可以取(124816) 中任意一值。

3.#pragma pack详细介绍:

想必大家也看烦了,那么下面我就开始为大家介绍#pragma pack的详细用法:

3.1 #pragma pack(show):

#pragma pack(show)显示当前内存对齐的字节数。也就是packing aligment
我们常说编译器默认8字节对齐我们怎么知道的呢?
如下图所示:

image image

在程序中#pragma pack(show)会在编译阶段提出一个警告,说明当前对齐字节数。

3.2 #pragma pack(push [, identifier] [, n])

单纯使用#pragma pack(push)会将当前的对齐字节数压入栈顶,并设置这个值为新的对齐字节数, 就是说不会改变这个值。
  而使用#pragma pack(push, n) 会将当前的对齐字节数压入栈顶,并设置n为新的对齐字节数。
  再就是这个#pragma pack(push, identifier [, n])会在上面的操作基础上为这个对齐字节数附上一个标识符, 这里注意这个标识符只能以($_字母)开始, 标识符中可以有($_字母数字),并且标识符不能是关键字(push, pop可以作为标识符)。这个标识符的作用我会在pop中详细介绍。
push的使用:

image image

3.3 #pragma pack(pop [, identifier] [, n])

同样单纯使用#pragma pack(pop)会弹出栈顶对齐字节数,并设置其为新的内存对齐字节数。

image image

使用#pragma pack(pop, n)情况就不同了, 他会弹出栈顶并直接丢弃,设置n为其新的内存对齐字节数。

image image

#pragma pack(pop, identifier [, n])较为复杂,编译器执行这条执行时会从栈顶向下顺序查找匹配的identifier,找到identifier相同的这个数之后将从栈顶到identifier,包括找到identifier全部pop弹出, 若没有找到则不进行任何操作。

image image

由于前面提到的pushpop也可以作为关键字所以可以设计出很有戏剧效果的预处理头:

image image

#pragma pack一系列的预处理指令在网络报文构造中有着重要的应用,是编译器处理内存的重要指令,同时我也希望各位面试官注意自身知识体系,不要再自己一知半解的情况下乱问问题,我会在下次写一篇关于C++内存对齐的详细介绍敬请期待!

以上是原博客内容

下面是我遇到的一点情况(见注释):

#pragma pack(show)//默认内存对其按照8个字节,==8
#pragma pack(4)//将8个字节对齐改成了4个字节
#pragma pack(show)//==4
typedef struct
{
    uint32_t iDeviceType;                          // see above defines
    char     szPath[512];                          // device path to use in FZ_Open
    char     szShortName[32];                      // a more user friendly name
    char     szSerial[16];                         // device serial number
    uint32_t iReserved[64];
} FZ_DEVICE_INFO;
#pragma pack(show)//==4,没有发生改变
#pragma pack()//将内存对齐设置变成默认的8个字节
#pragma pack(show)//==8

相关文章

  • 结构体对齐方式

    #pragma pack()用法详解

  • #pragma pack()用法

    在阅读代码特别是C语法代码的过程中,其实经常会遇到#pragma pack(n),#pragma pack(),#...

  • #pragma pack()

    计算机中内存空间都是按照byte划分的从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特...

  • iOS 一字节对齐

    一字节对齐的写法 #pragma pack(1) 结构体 #pragma pack() __attribute__...

  • 【嵌入式C】在Keil中结构体的字节对齐

    使用关键字#pragma pack (1)开始字节对齐,使用#pragma pack ()结束。 比如: 这样做的...

  • 【转】关于#pragma pack

    pack 为 struct, union 和 class 等的成员对齐指定字节边界. 与编译选项的 /Zp 开关不...

  • #pragma pack 指令详解!

    1.#pragma简述: 在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或...

  • #pragma pack(push,1)与#pragma pac

    这是给编译器用的参数设置,有关结构体字节对齐方式设置, #pragma pack是指定数据在内存中的对齐方式。 #...

  • C_language_renew07

    结构体大小结构体对齐原则: x86(linux 默认#pragma pack(4),window默认#pragma...

  • #pragma pack(n)的使用

    pragma pack(n)用于修改内存对齐方式,n表示n字节对齐

网友评论

    本文标题:#pragma pack()用法

    本文链接:https://www.haomeiwen.com/subject/bqlfrqtx.html