C++ C和C+之间有什么区别+;呼叫约定?

C++ C和C+之间有什么区别+;呼叫约定?,c++,c,compiler-construction,linker,calling-convention,C++,C,Compiler Construction,Linker,Calling Convention,正如我所知,调用约定依赖于编译器和体系结构。但是C和C++调用约定有什么明显的区别吗? < C和C++调用约定有什么明显的区别吗? 一般来说,没有。C++被故意设计为尽可能兼容C,特别是它使用C系统的二进制接口在所有系统上。 但是,C abi不满足C++所需的许多特性(特别是重载、命名空间和函数模板),因此C++编译器对函数的名称做了一些更改。这叫做 P>所以,为了使C和C++代码之间的函数调用工作,这些函数必须声明为“代码>外部”C“/CUT>,这禁用了名称的修改,并确保调用约定是C所期望的

正如我所知,调用约定依赖于编译器和体系结构。但是C和C++调用约定有什么明显的区别吗? < C和C++调用约定有什么明显的区别吗?

一般来说,没有。C++被故意设计为尽可能兼容C,特别是它使用C系统的二进制接口在所有系统上。 <>但是,C abi不满足C++所需的许多特性(特别是重载、命名空间和函数模板),因此C++编译器对函数的名称做了一些更改。这叫做

<> P>所以,为了使C和C++代码之间的函数调用工作,这些函数必须声明为“代码>外部”C“/CUT>,这禁用了名称的修改,并确保调用约定是C所期望的(但是我希望后面的这一方面是自动的,即使标准不强制这样做)。
C++还为C中不存在的成员函数(有时被调用)提供了额外的调用约定。但自由函数使用与C相同的调用约定,以给定系统上的为准。

语言之间不同调用约定的整个概念超出了任何给定语言(及其规范)。这就是它应该做的,这些事情与任何名副其实的语言的规范无关。基本上,您是对的,它位于编译器体系结构规范的特定实现的域中。当然,在给定语言的规范/标准中讨论的一些概念(如链接规范)可能会影响调用约定,但这不是计划好的结果

ABI的职责是对这些概念进行标准化/形式化,人们也没有义务尊重这些概念(可能是因为实现的色板变化很大)

实际上,规范需要忽略参数是如何传递的,不管它是在堆栈上还是在寄存器上,两者的组合,分配的顺序等等。这是执行人员和设计实际硬件的人员的工作,更重要的是指令集

<>强:因此:< /强>,无论是C,还是C++,标准化都不知道如何实现这些东西。因此,语言之间必须没有固有的差异。只是在应用的方式上。这就是编译器体系结构的领域

正如我所知,调用约定依赖于编译器和体系结构

< C和C++调用约定有什么明显的区别吗?

更好的问题是“有什么相似之处吗?”

是的:

在C++应用程序中声明的函数“代码>外部”C“/CODE”具有与C架构上使用的C函数相同的调用约定。


您对调用约定的任何其他假设都是推测的,可能发生相同的情况,但在逐个实例的基础上需要担心。

< P>在给定的编译器中,无论是C++还是C++函数都声明“代码> Extn”c,没有任何一个标准都需要相同的C和C++调用约定。必须使用与C函数相同的调用约定进行调用

这就是为什么具有相同参数和返回类型的函数指针和具有C链接的函数指针具有不同的类型。调用函数时,编译器可以从类型中知道使用哪个调用约定来调用函数,如果它们不同的话

在实践中,我不认为我曾经故意处理过一个例子,它在有C链接和没有C链接的自由函数之间使用不兼容的调用约定。通常,C++实现从其计划运行的系统的ABI中调用其调用约定,从而产生系统的其他用户可以理解的可链接对象(可执行文件和库)。 这不是必需的——标准不关心是否存在系统ABI,系统通常也不关心如何在自包含的可执行文件[*]中进行调用。除非有特别的理由不这样做,否则这样做是明智的。给定系统中的系统ABI可以或不必提及C++,如果不是,C++实现本身就涉及非C链接函数,但正如我所说,使C链接的函数使用相同的调用约定,就像它们确实具有C连接一般是明智的。

我说“不兼容”而不是“不同”,因为当然在C调用约定中没有提到的一些东西,但是需要在C++调用约定中指定。例如,如何将指针传递给成员函数。很可能这不是系统ABI所控制的,所以它只剩下C++实现。其原因是将指向成员函数的指针保留到C++实现,而不是系统ABI做的事情,制造商认为是C++编译器编写者的工作。 在取消调用约定后,请注意,在具有或不具有C链接的自由函数之间,名称损坏不可避免地是不同的。原因是C++名称的填充必须包括参数的类型(因为函数重载),而C名称的修改不能(因为外部函数声明有未指定的参数)。 [*]虽然我见过使用“错误”的调用约定会破坏事情的例子。ISTR是一个Windows mobile设备,如果您对堆栈的格式与操作系统预期的不同,则某些硬件异常会使该设备失效,因为操作系统试图追溯出错线程的堆栈,但无法执行。所以至少在那个版本上