问题
As I know, the calling convention is compiler and architecture dependent. But are there any clear differences between C and C++ calling conventions?
回答1:
But are there any clear differences between C and C++ calling conventions?
In general, there’s none. C++ was intentionally designed to be as much as possible compatible with C, and in particular it uses the C application binary interface on all systems.
But the C ABI doesn’t cater for a lot of features that C++ needs (in particular, overloading, namespaces and function templates) so the C++ compiler makes some changes to the names of functions. This is called name mangling
So in order for function calls between C and C++ code to work, such functions must be declared as extern "C"
which disables name mangling and makes sure that the calling conventions are those expected by C (but I expect that this latter aspect comes automatically, even though the standard doesn’t mandate this).
C++ also has additional calling conventions for member functions (sometimes called thiscall) which don’t exist in C. But free functions use the same calling convention as C, whichever that is on a given system.
回答2:
There is nothing in either standard that requires the C and C++ calling conventions to be the same on a given compiler, other than that a C++ function declared extern "C"
necessarily must be called with the same calling convention as a C function.
That's why a pointer-to-function and a pointer-to-function-with-C-linkage with the same parameters and return type, have different types. When the function is called, the compiler can know from the type which calling convention to call it with, if they are different.
In practice, I don't think I've ever knowingly dealt with an example that uses an incompatible calling convention between free functions with and without C linkage. Usually a C++ implementation adopts its calling convention from the ABI of the system that it's planning to run on, so as to produce linkable objects (executables and libraries) that other users of the system can understand in terms of the ABI.
This isn't required -- the standard doesn't care whether or not there is a system ABI, and the system doesn't usually care how calls are made within a self-contained executable[*]. It's just sensible to do it unless there's some extraordinary reason not to. The system ABI on a given system may or may not mention C++ -- if not then the C++ implementation is on its own as far as non-C-linkage functions are concerned, but as I say it is usually sensible to make functions that could have C linkage use the same calling convention as if they do have C linkage.
I say "incompatible" rather than "different", because of course there are some things that aren't mentioned in the C calling convention but need to be specified in the C++ calling convention. How to pass a pointer-to-member-function, for example. It may well be that this is not pinned down by the system ABI, and so is left to the C++ implementation. The reason for this is to leave the implementation of pointer-to-member-function up to the C++ implementation, rather than the system ABI doing something that the manufacturer considers to be the job of a C++ compiler writer.
With the calling convention out of the way, note that name mangling inevitably is different between a free function with or without C linkage. The reason is that C++ name mangling must include the types of the parameters (because of function overloading), whereas C name mangling must not (because of extern function declarations with unspecified parameters).
[*] Although I've seen examples where using the "wrong" calling convention does break things. ISTR a Windows mobile device where if you formatted the stack differently from what the OS expected, then certain hardware exceptions would take out the device because the OS tried to retrace the stack of the offending thread, and couldn't. So at least on that OS version, probably around 2005, if you wanted the OS's diagnostics to work then you had to use the Windows calling conventions internally. Or anyway the part of the calling convention relating to stack frame format. This was entirely our screwup, of course, but I don't know whether we could have fixed it properly by installing our own handlers for the hardware exceptions, rather than working around them by not causing the exceptions in the first place. It did mean that a user-mode process could trivially take the OS down with a stack overrun, though, and also that it was harder to debug our code than on other Windowses. So we slightly blamed the OS.
回答3:
As I know, the calling convention is compiler and architecture dependent.
Yes.
But are there any clear differences between C and C++ calling conventions?
Better question is "Are there any similarities?"
Yes:
A function declared extern "C"
inside a C++ application has the same calling convention used by a C function on that architecture.
Any other assumptions you make about calling conventions are speculative and may happen to be the same but you need to worry about that on a case by case bases.
回答4:
The whole notion of varying calling conventions between languages goes beyond any given language (and its spec). And that's how it should be, such things are of no concern to the specification of any language which is worth its name. Basically, you're right, it is in the domain of a specific implementation of a specification - of the compiler architecture. Sure, some notions discussed in the specification/standard of a given language like linkage specification can affect the calling convention, but it's not a planned consequence.
ABI's duty is to standardize/formalize such concepts which, then again, people have no duty to respect (and likely because the colorful palette of implementations varies quite a bit)
Really, the specification needs to be oblivious to how parameters are passed on, be it ending up on the stack or registers, a combination of both, ordering of allocation etc. That's the job of the guys working on the implementation and the people who design the actual hardware, more importantly the instruction sets.
Therefore: Neither C, nor C++, as standardized have any say in how stuff is implemented. Therefore, there must be no difference inherent to the languages. Only in the way they're applied. And that's the field of the compiler architecture.
回答5:
No C or C++ standard defines an ABI. This is an intentional design decision which allows compiler writers the freedom to create as efficient an implementation as possible.
Over time a C calling convention called cdecl has become the de-facto standard on x86 architectures. There are similar de-facto standards for C code running on AMD64 machines, but they differ between UNIX and Windows operating systems.
On Unix machines there is some movement towards a common C++ ABI based on the Itanium C++ ABI published by Intel. However, due to the extra complexity of C++, different versions of the same compiler and even different compiler switches often produce machine code conforming to incompatible ABIs.
Use of extern "C" { ... }
can often be relied on to force a compiler to implement a function using the de-facto C ABI, but even this is not required by the C++ standard.
If you're interested in a comprehensive description of the current C++ ABIs, then you should look at Agner Fog's "Calling conventions for different C++ compilers and operating systems".
来源:https://stackoverflow.com/questions/11257383/what-are-the-differences-between-c-and-c-calling-conventions