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

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


当前回答

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

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

其他回答

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)。

为什么要使用它?

减少结构的内存

为什么不应该使用它?

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

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

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

数据元素(例如类和结构的成员)通常在当前一代处理器的WORD或DWORD边界上对齐,以提高访问时间。在32位处理器上,在不能被4整除的地址处检索DWORD至少需要一个额外的CPU周期。如果你有三个char成员char a b c;,它们实际上会占用6到12个字节的存储空间。

#pragma允许你覆盖这个,以实现更有效的空间使用,以访问速度为代价,或为了不同编译器目标之间存储的数据的一致性。从16位代码到32位代码的转换给我带来了很多乐趣;我预计移植到64位代码也会对某些代码造成同样的困扰。

它告诉编译器要将结构中的对象对齐到的边界。例如,如果我有这样的东西:

struct foo { 
    char a;
    int b;
};

对于典型的32位机器,您通常“希望”在a和b之间有3个字节的填充,以便b将在4字节的边界上着陆,以最大限度地提高其访问速度(这通常是默认情况)。

然而,如果你必须匹配一个外部定义的结构,你想要确保编译器完全根据外部定义来布局你的结构。在这种情况下,你可以给编译器一个#pragma包(1)来告诉它不要在成员之间插入任何填充——如果结构的定义包含了成员之间的填充,你可以显式地插入它(例如,典型的成员名为unusedN或ignoreN,或者类似的顺序)。