在平台ABI中键入规范

可以安全地假设在任何实际可用的平台ABI中定义了哪些项目?

> CHAR_BIT的值
>尺寸,对齐要求和对象表示:

> void *,size_t,ptrdiff_t
> unsigned char和signed char
> intptr_t和uintptr_t
>浮动,双重和长双
>短而长
> int和long(但在这里我期待“不”)
>指向平台ABI指定这些属性的对象类型的指针
>指向函数的指针,其类型仅涉及平台ABI指定这些属性的类型

>空对象指针的对象表示
>空函数指针的对象表示

例如,如果我有一个库(由未知但符合ABI的编译器编译)发布此函数

void* foo(void *bar,size_t baz,void* (*qux)());

我可以假设能够在我的程序中安全地调用它,无论我使用哪个编译器?

或者,反过来说,如果我正在编写一个库,是否有一组类型,如果我将库的公共接口限制为此集,它将保证在它构建的所有平台上都可用?

解决方法

C标准包含附录中的整个部分,总结如下:

J.3 Implementation-defined behavior

一个完全随机的子集:

>一个字节中的位数
> signed char和unsigned char中的哪一个与char相同
>多字节和宽字符串的文本编码
>有符号整数表示
>将指针转换为整数的结果,反之亦然(6.3.2.3).请注意,这意味着任何指针,而不仅仅是对象指针.

更新:解决有关ABI的问题:ABI(应用程序二进制接口)不是标准化概念,并且在任何地方都没有说实现必须指定ABI. ABI的成分部分是语言的实现定义行为(尽管不是全部;例如,签名到无符号转换是实现定义的,但不是ABI的一部分),以及大多数实现定义的方面.语言由硬件决定(例如有符号整数表示,浮点表示,指针大小).

但是,ABI的更重要的方面是诸如函数调用如何工作,即存储参数的位置,谁负责清理内存等等.两个编译器就这些约定达成一致以使其代码成为关键是至关重要的.兼容.

实际上,ABI通常是实施的结果.编译器完成后,它会根据其实现确定ABI.它可以记录这个ABI,并且其他编译器和同一编译器的未来版本可能希望坚持这些约定.对于x86上的C实现,这种方法运行得相当好,并且只有少数(通常记录良好的)自由参数需要通信才能使代码具有可互操作性.但是对于其他语言,尤其是C语言,你有一个完全不同的画面:C的标准ABI几乎没有任何东西可以接近.微软的编译器在每个版本中打破了C ABI. GCC努力维护不同版本的ABI兼容性,并使用已发布的Itanium ABI(具有讽刺意味的是现在已经死的架构).其他编译器可能会做自己的,完全不同的事情. (然后你当然会遇到C标准库实现的问题,例如你的字符串是否包含一个,两个或三个指针,以及它们的顺序是什么?)

总结一下:编译器的ABI的许多方面,特别是与C有关,都由硬件架构决定.只要正确传达函数调用约定等某些方面,相同硬件的不同C编译器就应该生成兼容的二进制代码.但是,对于更高级别的语言,所有赌注都是关闭的,并且两个不同的编译器是否可以生成可互操作的代码必须根据具体情况来决定.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...