Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
单独编译代码中struct的二进制兼容性_C_Struct_Binary Compatibility - Fatal编程技术网

单独编译代码中struct的二进制兼容性

单独编译代码中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;/*链接计数*/ /*……等等*/ } 我的

给定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;/*链接计数*/
/*……等等*/
}
我的内核已经编译好了。现在,当我使用这个定义编译新代码时,它们具有二进制兼容性。这在哪里保证?我所知道的唯一保证是:

  • 第一个元素的偏移量为0
  • 稍后声明的元素具有更高的偏移量
  • 因此,如果内核代码以完全相同的方式(在C代码中)声明
    struct stat64
    ,那么我知道二进制形式有:

  • st_dev
    @offset 0
  • st\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实现