【发布时间】:2018-05-17 17:08:41
【问题描述】:
我找到了一个来源,作者对变量的对齐和顺序做出了如下假设:
#include <stdio.h>
#pragma pack(push)
#pragma pack(1)
int a;
char b;
char c;
#pragma pack(pop)
void foo(FILE *f)
{
fwrite(f, &a, 6);
}
我知道在结构的上下文中打包 pragma。但这也可以用于文件范围变量吗?如果这适用于给定的编译器,是否在 C 标准中定义?
【问题讨论】:
-
除了您的问题之外,我还要问一些其他问题:作者如何确保分配的变量
a、b和c在二进制文件中具有完全相同的顺序? (AFAIK,这不是标准所授予的。)否则,即使sizeof a + sizeof b + sizeof c是 6,fwrite(f, &a, 6);也不是预期的。我至少会在 @ 中捆绑a、b和c987654330@。 (不,实际上,我不敢做这种骇人听闻的事情......);-) -
C 标准识别(定义)
#pragma,但该标准没有定义任何打包编译指示。因此,#pragma的行为取决于编译器。如果编译器不能识别该指令,它必须忽略它——仅此而已。因此,请阅读编译器手册。不要假设它对任何其他编译器都一样(尽管它可能)。当然,C 标准并没有规定它的含义。 -
C 标准不保证此处的排序。事实上,由于这里的 a、b、c 具有外部链接,因此不可能保证它们的顺序,因为另一个翻译单元可以以另一种顺序定义它们。所以在这里打包是非常特定于编译器的,一开始可能是一个糟糕的主意。 (将另一个文件添加到您的编译中,该文件具有与 pragma pack 相同的三个变量,但变量的顺序不同,看看会发生什么)。
-
@Art 变量 a,b,c 在当前翻译单元中定义。如果它们是在其他地方定义的,您将收到有关重复符号的链接器错误。所以我不同意你担心“另一个翻译单元可以按另一个顺序定义它们”。
-
@harper C11 6.2.2:“在构成整个程序的翻译单元和库集合中,具有外部链接的特定标识符的每个声明都表示相同的对象”和“如果声明对象的标识符具有文件范围且没有存储类说明符,它的链接是外部的。"
标签: c visual-studio