我想知道是否有人可以向我解释一下#pragma包预处理器语句是做什么的,更重要的是,为什么人们想要使用它。
我查看了MSDN页面,它提供了一些见解,但我希望从有经验的人那里听到更多。我以前在代码中见过它,尽管我似乎再也找不到在哪里了。
我想知道是否有人可以向我解释一下#pragma包预处理器语句是做什么的,更重要的是,为什么人们想要使用它。
我查看了MSDN页面,它提供了一些见解,但我希望从有经验的人那里听到更多。我以前在代码中见过它,尽管我似乎再也找不到在哪里了。
当前回答
编译器可以对结构中的成员进行对齐,以在特定平台上实现最大性能。#pragma包指令允许你控制对齐方式。通常,您应该将其保留为默认值以获得最佳性能。如果你需要传递一个结构到远程机器,你通常会使用#pragma pack 1来排除任何不需要的对齐。
其他回答
编译器可以将结构成员放在特定的字节边界上,以提高特定体系结构上的性能。这可能会在成员之间留下未使用的填充。结构填料迫使构件连续。
这可能很重要,例如,如果您需要一个结构符合特定的文件或通信格式,其中您需要数据位于序列中的特定位置。然而,这种用法不处理端部性问题,因此尽管使用了,但它可能是不可移植的。
它还可以精确地覆盖一些I/O设备(例如UART或USB控制器)的内部寄存器结构,以便通过结构而不是直接地址访问寄存器。
#pragma用于向编译器发送不可移植(仅在此编译器中)消息。像禁用某些警告和包装结构是常见的原因。如果在编译时将警告作为错误标志打开,则禁用特定警告特别有用。
#pragma pack特别用于指示被打包的结构体不应该让其成员对齐。当您有一个内存映射接口到某个硬件,并且需要能够准确控制不同结构成员指向的位置时,它非常有用。这显然不是一个很好的速度优化,因为大多数机器在处理对齐数据时要快得多。
使用#pragma pack(push,1)和#pragma pack(pop)来撤销换行
请注意,#pragma pack提供了其他实现数据一致性的方法(例如,有些人使用#pragma pack(1)来实现应该通过网络发送的结构)。例如,请参阅以下代码及其后续输出:
#include <stdio.h>
struct a {
char one;
char two[2];
char eight[8];
char four[4];
};
struct b {
char one;
short two;
long int eight;
int four;
};
int main(int argc, char** argv) {
struct a twoa[2] = {};
struct b twob[2] = {};
printf("sizeof(struct a): %i, sizeof(struct b): %i\n", sizeof(struct a), sizeof(struct b));
printf("sizeof(twoa): %i, sizeof(twob): %i\n", sizeof(twoa), sizeof(twob));
}
回显如下: Sizeof (struct a): 15, Sizeof (struct b): 24 Sizeof (twoa): 30, Sizeof (twob): 48
注意结构体a的大小和字节数是一样的,但是结构体b添加了填充(关于填充的详细信息请参见此)。通过这样做,而不是#pragma包,你可以控制将“连线格式”转换为适当的类型。例如,“char 2[2]”转换为“short int”等等。
它告诉编译器要将结构中的对象对齐到的边界。例如,如果我有这样的东西:
struct foo {
char a;
int b;
};
对于典型的32位机器,您通常“希望”在a和b之间有3个字节的填充,以便b将在4字节的边界上着陆,以最大限度地提高其访问速度(这通常是默认情况)。
然而,如果你必须匹配一个外部定义的结构,你想要确保编译器完全根据外部定义来布局你的结构。在这种情况下,你可以给编译器一个#pragma包(1)来告诉它不要在成员之间插入任何填充——如果结构的定义包含了成员之间的填充,你可以显式地插入它(例如,典型的成员名为unusedN或ignoreN,或者类似的顺序)。
为什么要使用它?
减少结构的内存
为什么不应该使用它?
这可能会导致性能损失,因为某些系统在对齐的数据上工作得更好 一些机器将无法读取未对齐的数据 代码不可移植