#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值可以取(1
, 2
, 4
, 8
, 16
) 中任意一值。
3.#pragma pack详细介绍:
想必大家也看烦了,那么下面我就开始为大家介绍#pragma pack的详细用法:
3.1 #pragma pack(show):
#pragma pack(show)
显示当前内存对齐的字节数。也就是packing aligment
。
我们常说编译器默认8字节对齐我们怎么知道的呢?
如下图所示:


在程序中#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的使用:


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


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


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


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


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