单独编译代码中struct的二进制兼容性
给定CPU体系结构,结构的确切二进制形式是否准确确定 例如,单独编译代码中struct的二进制兼容性,c,struct,binary-compatibility,C,Struct,Binary Compatibility,给定CPU体系结构,结构的确切二进制形式是否准确确定 例如,struct stat64由glibc和Linux内核使用。我看到glibc在sysdeps/unix/sysv/linux/x86/bits/stat.h中把它定义为: struct stat64{ __dev_t st_dev;/*设备*/ #ifdef\uuux86\u64__ __ino64\u t st\u ino;/*文件序列号*/ __nlink\u t st\u nlink;/*链接计数*/ /*……等等*/ } 我的
struct stat64
由glibc和Linux内核使用。我看到glibc在sysdeps/unix/sysv/linux/x86/bits/stat.h中把它定义为:
struct stat64{
__dev_t st_dev;/*设备*/
#ifdef\uuux86\u64__
__ino64\u t st\u ino;/*文件序列号*/
__nlink\u t st\u nlink;/*链接计数*/
/*……等等*/
}
我的内核已经编译好了。现在,当我使用这个定义编译新代码时,它们具有二进制兼容性。这在哪里保证?我所知道的唯一保证是:
struct stat64
,那么我知道二进制形式有:
st_dev
@offset 0st\u ino
@偏移量至少sizeof(\uu dev\u t)
但我目前还不知道有什么方法可以确定圣伊诺的偏移量。Kernighan和Ritchie给出了一个简单的例子
struct X{
字符c;
int i;
}
其中在我的x86-64机器上,offsetof(struct X,i)==4
。也许有一些通用的对齐规则可以确定每个CPU体系结构的结构的确切二进制形式
给定CPU体系结构,结构的确切二进制形式是否准确确定
不,结构的表示或布局(“二进制形式”)最终由C实现决定,而不是由CPU体系结构决定。大多数用于正常用途的C实现都遵循制造商和/或操作系统提供的建议。但是,在某些情况下,例如,特定类型的某个对齐可能会提供稍好的性能,但并不需要,因此一个C实现可能会选择需要该对齐,而另一个则不需要,这可能会导致不同的结构布局
此外,C实现可能是为特殊目的而设计的,例如提供与遗留代码的兼容性,在这种情况下,它可能会选择复制某些旧编译器与另一个体系结构的对齐方式,而不是使用目标处理器所需的对齐方式
但是,让我们考虑使用一个C实现在单独编译中的结构。然后C 2018第6.2.7 1条规定:
…此外,如果在单独的翻译单元中声明的两个结构、联合或枚举类型的标记和成员满足以下要求,则它们是兼容的:如果其中一个使用标记声明,则另一个应使用相同的标记声明。如果两者都是在各自翻译单元内的任何地方完成的,则以下附加要求适用:其成员之间应存在一对一的对应关系,以便每对对应成员声明兼容类型;如果使用对齐说明符声明对中的一个成员,则使用等效对齐说明符声明另一个成员;如果该对中的一个成员用名称声明,则另一个成员用相同的名称声明。对于两个结构,应按照相同的顺序声明相应的构件。对于两个结构或接头,相应的位字段应具有相同的宽度 因此,如果两个结构在单独的翻译单元中声明相同,或者在该段中允许有细微的变化,那么它们是兼容的,这实际上意味着它们具有相同的布局或表示 从技术上讲,这段话只适用于同一程序的不同翻译单元。C标准定义了一个程序的行为;它没有明确地定义程序(或程序片段,例如内核扩展)和操作系统之间的交互,但在某种程度上,您可能会考虑操作系统和在其中运行的所有操作作为一个程序。然而,出于实际目的,它适用于使用该C实现编译的所有内容 这意味着,只要使用与编译内核相同的C实现,相同声明的结构将具有相同的表示形式 另一个考虑因素是,我们可能会使用不同的编译器来编译内核和编译程序。当用户更喜欢使用GCC时,内核可能会使用Clang进行编译。在这种情况下,编译器需要记录他们的行为。C标准不能保证兼容性,但是编译器可以,如果他们选择的话,也许通过记录他们遵守特定的应用程序二进制接口(ABI) 还要注意,上面讨论的“C实现”不仅是一个特定的编译器,而且是一个具有特定开关的特定编译器。各种开关可能会改变编译器的行为方式,从而有效地导致不同的C实现,例如符合一个或另一个C标准版本的开关、影响结构是否打包的开关、影响整数类型大小的开关等等 给定CPU体系结构,结构的确切二进制形式是否准确确定 不,结构的表示或布局(“二进制形式”)最终由C实现决定,而不是由CPU体系结构决定。大多数用于正常用途的C实现都遵循制造商和/或操作系统提供的建议。但是,在某些情况下,例如,特定类型的某个对齐可能会提供稍好的性能,但并不需要,因此一个C实现可能会选择需要该对齐,而另一个则不需要,这可能会导致不同的结构布局 此外,还可以设计一个C实现