我想知道是否有人可以向我解释一下#pragma包预处理器语句是做什么的,更重要的是,为什么人们想要使用它。

我查看了MSDN页面,它提供了一些见解,但我希望从有经验的人那里听到更多。我以前在代码中见过它,尽管我似乎再也找不到在哪里了。


当前回答

I've used it in code before, though only to interface with legacy code. This was a Mac OS X Cocoa application that needed to load preference files from an earlier, Carbon version (which was itself backwards-compatible with the original M68k System 6.5 version...you get the idea). The preference files in the original version were a binary dump of a configuration structure, that used the #pragma pack(1) to avoid taking up extra space and saving junk (i.e. the padding bytes that would otherwise be in the structure).

代码的原始作者还使用#pragma pack(1)来存储在进程间通信中用作消息的结构。我认为这里的原因是为了避免未知或更改填充大小的可能性,因为代码有时会通过从开始计算字节数来查看消息结构的特定部分(ewww)。

其他回答

I've used it in code before, though only to interface with legacy code. This was a Mac OS X Cocoa application that needed to load preference files from an earlier, Carbon version (which was itself backwards-compatible with the original M68k System 6.5 version...you get the idea). The preference files in the original version were a binary dump of a configuration structure, that used the #pragma pack(1) to avoid taking up extra space and saving junk (i.e. the padding bytes that would otherwise be in the structure).

代码的原始作者还使用#pragma pack(1)来存储在进程间通信中用作消息的结构。我认为这里的原因是为了避免未知或更改填充大小的可能性,因为代码有时会通过从开始计算字节数来查看消息结构的特定部分(ewww)。

为什么要使用它?

减少结构的内存

为什么不应该使用它?

这可能会导致性能损失,因为某些系统在对齐的数据上工作得更好 一些机器将无法读取未对齐的数据 代码不可移植

编译器可以将结构成员放在特定的字节边界上,以提高特定体系结构上的性能。这可能会在成员之间留下未使用的填充。结构填料迫使构件连续。

这可能很重要,例如,如果您需要一个结构符合特定的文件或通信格式,其中您需要数据位于序列中的特定位置。然而,这种用法不处理端部性问题,因此尽管使用了,但它可能是不可移植的。

它还可以精确地覆盖一些I/O设备(例如UART或USB控制器)的内部寄存器结构,以便通过结构而不是直接地址访问寄存器。

你可能只在对某些硬件(例如内存映射设备)编码时才会使用它,这些硬件对寄存器排序和对齐有严格的要求。

然而,这似乎是实现这一目标的一个相当生硬的工具。一个更好的方法是在汇编程序中编写一个迷你驱动程序,并给它一个C调用接口,而不是摸索这个pragma。

我见过有人使用它来确保一个结构占用整个缓存行,以防止在多线程上下文中错误共享。如果你将有大量的对象,在默认情况下将它们松散地打包,它可以节省内存并提高缓存性能,尽管未对齐的内存访问通常会降低速度,所以可能会有一个缺点。