C有标准的ABI吗?

fre*_*low 29 c abi

其他地方的讨论:

C++没有标准的ABI

但C也不是吗?

在任何给定的平台上它几乎都可以.如果没有语言交流,那么作为语言间交流的通用语言是没有用的.

你对此有何看法?

Jer*_*myP 31

C没有定义ABI.实际上,它会向后弯曲以避免定义ABI.那些喜欢我的人,他们花了大部分编程生活用C编程的16/32/64位架构,8位字节,2的补码算法和平面地址空间,通常会很惊讶于阅读复杂的语言目前的C标准.

例如,阅读有关指针的内容.标准没有说"指针是地址"这么简单,因为它会对ABI做出假设.特别是,它允许指针位于不同的地址空间中并具有不同的宽度.

ABI是从语言的执行模型到特定机器/操作系统/编译器组合的映射.在语言规范中定义一个是没有意义的,因为这会冒一些体系结构排除C实现的风险.

  • @Hibou57当时我写了答案,目前的C标准是C99.我怀疑C11有多少变化.小型,大型和中型内存模型不是C的一部分,而是8086架构上大多数C实现的一部分. (6认同)

Chr*_*oph 16

C原则上没有标准的ABI,但在实践中,这很少重要:您可以执行您的操作系统供应商所做的事情.

以x86 Windows上的调用约定为例:Windows API使用所谓的"标准"调用约定(stdcall).因此,任何想要与OS接口的编译器都需要实现它.但是,stdcall不支持所有C90语言功能(例如,调用没有原型的函数,可变函数).由于Microsoft提供了C编译器,因此需要第二个调用约定,称为"C"调用约定(cdecl).Windows上的大多数C编译器都将此作为默认调用约定,因此可以互操作.

原则上,C++也可能发生同样的情况,但由于C++ ABI(包括调用约定)必然要复杂得多,编译器供应商并不同意单个ABI,但仍然可以通过回退来实现互操作extern "C".

  • 这是正确的,但还不够明确。这并不是说供应商之间没有就通用 ABI 达成一致(这可以由标准化委员会解决)。更多的是同一家供应商由于不总是预测未来的发展而在不同时间与自己不一致。 (3认同)

Man*_*res 7

尽管已经多次尝试为跨多个操作系统(特别是 Unix 系统上的 i386)的给定体系结构定义单个 ABI,但这些努力并未取得如此成功。相反,操作系统倾向于定义自己的 ABI...

引用... Linux 系统编程第 4 页。


Adr*_*Cox 6

C的ABI是特定于平台的-它涵盖了诸如寄存器分配和调用约定之类的问题,这些问题显然是特定于特定处理器的。这里有些例子:

x86有许多调用约定,Windows下的扩展名用于声明使用哪个。嵌入式Linux的平台ABI也随着时间而改变,从而导致用户空间不兼容。在此处查看有关ARM Linux端口的一些历史记录,其中显示了向较新的ABI过渡的问题。


APr*_*mer 5

ABI,即使对于C,也有与平台无关的部分,依赖于处理器的部分(应该保存哪些寄存器,用于传递参数,......)和依赖于OS的部分(或多或少)与处理器相同的因素,因为一些选择不是由架构强加的,而是权衡的结果,加上一些操作系统有一个独立于语言的异常概念,因此任何语言的编译器都必须生成正确的事情来处理那些,线程的处理也可能会对ABI施加影响 - 如果寄存器指向TLS,则不能将它用于你想要的东西.

理论上,每个编译器都可能有自己的ABI.但通常,对于一对处理器/ OS,ABI由OS供应商修复,该供应商通常还提供C编译器和使用该ABI且竞争者更喜欢兼容的公共库.(如果某些操作系统有例外情况,我不会感到惊讶,因为C不是主要的编程语言).

但操作系统供应商可能出于某种原因切换ABI(新版本的处理器可能具有您想在ABI中使用的功能 - 例如有些人要求x86_64允许使用所有寄存器的32位ABI) .在迁移阶段 - 可能需要很长时间 - 您可能需要处理两个ABI.


Cha*_*pul 5

C 也没有,对吗?
正确的

在任何给定的平台上它几乎都是如此。如果缺乏一种语言,它就无法作为跨语言交流的通用语言。
几乎可能指的是 C 编译器供应商选择的特定于体系结构的默认值,并在其他语言中进行了调整。因此,如果 Keil 的 ARM C 编译器将使用从左到右的小端参数排序和堆栈来传递参数和一些预定的寄存器作为返回值,那么来自其他编译器的 extern“C” 将假定与这种方案兼容。

虽然此类协议可能被视为 ABI 的一部分,但与 JVM 浏览器沙箱等托管执行上下文不同,它本身远非完整的标准 ABI。