9

As I know, the calling convention is compiler and architecture dependent. But are there any clear differences between C and C++ calling conventions?

Kadiam
  • 303
  • 4
  • 12
  • Please check this first : [Stackoverflow][1] [1]: http://stackoverflow.com/questions/949862/what-are-the-different-calling-conventions-in-c-c-and-what-do-each-mean – Saiful Jun 29 '12 at 07:02
  • @Saif Yes I saw that before. But that question is about the calling conventions in C/C++ compilers. Not about the differences between C calling convention and C++ calling convention. Anyway thanks – Kadiam Jun 29 '12 at 07:15

5 Answers5

11

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.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 5
    I have not seen anything anywhere that guarantees anything said here. The only calling convention in C++ that are the same as C are functions declared as extern "C". But I have been know to be wrong before. If you have a reference it would be great. – Martin York Jun 29 '12 at 07:10
  • 2
    @LokiAstari There are several books by Bjarne Stroustrup that all say exactly that. – user207421 Jun 29 '12 at 07:26
  • While C++ has been designed so that it is possible to reuse the C calling convention for what is shared, the only way to be sure is the use of extern "C" and I'd be surprised if no compiler ever took the advantage of insight to fix issues with an earlier C calling conventions. – AProgrammer Jun 29 '12 at 08:06
  • 2
    You need to discuss name mangling a little bit. C ABIs have no, or minimal, name mangling. C++ mangles everything that isn't declared `extern "C"`. Mangling encodes the argument and return types, and is done on all functions, member or not, in C++. – sfstewman Jun 29 '12 at 13:52
  • @sfstewman I’m not sure name mangling and calling conventions are really all that related. Calling conventions describe how the call stack is laid out and how jumps into and out of functions are performed. Name mangling is a compiler internal convention of treating names which aren’t compatible with C ABI (I therefore also think that C does no name mangling by definition). – Konrad Rudolph Jun 29 '12 at 13:54
  • You basically had this in your answer, and I missed it because (a) I was reading fast (my bad!), and (b) you didn't refer to it as 'name mangling.' You might want to add a link to http://en.wikipedia.org/wiki/Name_mangling to provide a bit more info, for the interested reader. – sfstewman Jun 29 '12 at 14:07
  • @sfstewman Good point, added (and modified the post a bit in the process, hopefully for the better). – Konrad Rudolph Jun 29 '12 at 14:19
  • @Konrad: I think maybe C does a tiny bit of name mangling, because IIRC there's something about only the first N characters of an external name being significant, where N is implementation-defined. So the "mangling" is to truncate the name. I may have remembered wrong, though, or that might be a pre-standard implementation bodge. And you could still say that this still isn't "name mangling" by the C++ definition, even if it is name mangling by the English definition. – Steve Jessop Jul 03 '12 at 11:08
  • @Kasnel The stack management is only part of the calling convention insofar as it affects the treatment of arguments and/or return value. For all *observable* functions, i.e. all that are interoperable (`extern "C"`), this is guaranteed to be the same. For all other functions, the compilers essentially do whatever they want to optimise, i.e. remove calls completely (inlining), change signatures to avoid copying ((N)RVO), or to implement tail-call optimisation. – Konrad Rudolph Jul 04 '12 at 12:24
7

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.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
4

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.

Martin York
  • 257,169
  • 86
  • 333
  • 562
3

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.

  • thanks @Domagoj But what about the name-mangling? Is having name-mangling a difference between C an C++ calling conventions? – Kadiam Jun 29 '12 at 07:37
  • @Kasnel It is derived off C, well, partially (there's been a lot of time to evolve, so qualifications need to be employed). It is standardized - as well - by the application binary interface. And there is basically no difference. Usually it changes as compilers need to introduce new stuff, name mangling has been around for a very long time and there is no need to fix what isn't broken. –  Jun 29 '12 at 07:40
2

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".

andypea
  • 1,343
  • 11
  • 22