There are different calling conventions available in C/C++: stdcall
, extern
, pascal
, etc. How many such calling conventions are available, and what do each mean? Are there any links that describe these?
-
See [Wikipedia article](http://en.wikipedia.org/wiki/X86_calling_conventions) and also Raymond Chen's series on the history of calling conventions: [part 1](http://blogs.msdn.com/oldnewthing/archive/2004/01/02/47184.aspx), [part 2](http://blogs.msdn.com/oldnewthing/archive/2004/01/07/48303.aspx), [part 3](http://blogs.msdn.com/oldnewthing/archive/2004/01/08/48616.aspx) (this is mostly what you're asking), [part 4](http://blogs.msdn.com/oldnewthing/archive/2004/01/13/58199.aspx), and [part 5](http://blogs.msdn.com/oldnewthing/archive/2004/01/14/58579.aspx). – Rom Jun 04 '09 at 11:07
-
I googled for "calling conventions": - http://msdn.microsoft.com/en-us/library/984x0h58.aspx - http://msdn.microsoft.com/en-us/library/wda6h6df.aspx – Daniel Earwicker Jun 04 '09 at 11:07
6 Answers
Simple answer: I use cdecl, stdcall, and fastcall. I seldom use fastcall. stdcall is used to call Windows API functions.
Detailed answer (Stolen from Wikipedia):
cdecl - In cdecl, subroutine arguments are passed on the stack. Integer values and memory addresses are returned in the EAX register, floating point values in the ST0 x87 register. Registers EAX, ECX, and EDX are caller-saved, and the rest are callee-saved. The x87 floating point registers ST0 to ST7 must be empty (popped or freed) when calling a new function, and ST1 to ST7 must be empty on exiting a function. ST0 must also be empty when not used for returning a value.
syscall - This is similar to cdecl in that arguments are pushed right-to-left. EAX, ECX, and EDX are not preserved. The size of the parameter list in doublewords is passed in AL.
pascal - the parameters are pushed on the stack in left-to-right order (opposite of cdecl), and the callee is responsible for balancing the stack before return.
stdcall - The stdcall[4] calling convention is a variation on the Pascal calling convention in which the callee is responsible for cleaning up the stack, but the parameters are pushed onto the stack in right-to-left order, as in the _cdecl calling convention. Registers EAX, ECX, and EDX are designated for use within the function. Return values are stored in the EAX register.
fastcall - __fastcall convention (aka __msfastcall) passes the first two arguments (evaluated left to right) that fit into ECX and EDX. Remaining arguments are pushed onto the stack from right to left.
vectorcall - In Visual Studio 2013, Microsoft introduced the __vectorcall calling convention in response to efficiency concerns from game, graphic, video/audio, and codec developers.[7] For IA-32 and x64 code, __vectorcall is similar to __fastcall and the original x64 calling conventions respectively, but extends them to support passing vector arguments using SIMD registers. For x64, when any of the first six arguments are vector types (float, double, __m128, __m256, etc.), they are passed in via the corresponding XMM/YMM registers. Similarly for IA-32, up to six XMM/YMM registers are allocated sequentially for vector type arguments from left to right regardless of position. Additionally, __vectorcall adds support for passing homogeneous vector aggregate (HVA) values, which are composite types consisting solely of up to four identical vector types, using the same six registers. Once the registers have been allocated for vector type arguments, the unused registers are allocated to HVA arguments from left to right regardless of position. Resulting vector type and HVA values are returned using the first four XMM/YMM registers.
safecall - n Delphi and Free Pascal on Microsoft Windows, the safecall calling convention encapsulates COM (Component Object Model) error handling, thus exceptions aren't leaked out to the caller, but are reported in the HRESULT return value, as required by COM/OLE. When calling a safecall function from Delphi code, Delphi also automatically checks the returned HRESULT and raises an exception if necessary.
The safecall calling convention is the same as the stdcall calling convention, except that exceptions are passed back to the caller in EAX as a HResult (instead of in FS:[0]), while the function result is passed by reference on the stack as though it were a final "out" parameter. When calling a Delphi function from Delphi this calling convention will appear just like any other calling convention, because although exceptions are passed back in EAX, they are automatically converted back to proper exceptions by the caller. When using COM objects created in other languages, the HResults will be automatically raised as exceptions, and the result for Get functions is in the result rather than a parameter. When creating COM objects in Delphi with safecall, there is no need to worry about HResults, as exceptions can be raised as normal but will be seen as HResults in other languages.
Microsoft X64 Calling Convention - The Microsoft x64 calling convention[12][13] is followed on Windows and pre-boot UEFI (for long mode on x86-64). It uses registers RCX, RDX, R8, R9 for the first four integer or pointer arguments (in that order), and XMM0, XMM1, XMM2, XMM3 are used for floating point arguments. Additional arguments are pushed onto the stack (right to left). Integer return values (similar to x86) are returned in RAX if 64 bits or less. Floating point return values are returned in XMM0. Parameters less than 64 bits long are not zero extended; the high bits are not zeroed.
When compiling for the x64 architecture in a Windows context (whether using Microsoft or non-Microsoft tools), there is only one calling convention – the one described here, so that stdcall, thiscall, cdecl, fastcall, etc., are now all one and the same.
In the Microsoft x64 calling convention, it is the caller's responsibility to allocate 32 bytes of "shadow space" on the stack right before calling the function (regardless of the actual number of parameters used), and to pop the stack after the call. The shadow space is used to spill RCX, RDX, R8, and R9,[14] but must be made available to all functions, even those with fewer than four parameters.
The registers RAX, RCX, RDX, R8, R9, R10, R11 are considered volatile (caller-saved).[15]
The registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 are considered nonvolatile (callee-saved).[15]
For example, a function taking 5 integer arguments will take the first to fourth in registers, and the fifth will be pushed on the top of the shadow space. So when the called function is entered, the stack will be composed of (in ascending order) the return address, followed by the shadow space (32 bytes) followed by the fifth parameter.
In x86-64, Visual Studio 2008 stores floating point numbers in XMM6 and XMM7 (as well as XMM8 through XMM15); consequently, for x86-64, user-written assembly language routines must preserve XMM6 and XMM7 (as compared to x86 wherein user-written assembly language routines did not need to preserve XMM6 and XMM7). In other words, user-written assembly language routines must be updated to save/restore XMM6 and XMM7 before/after the function when being ported from x86 to x86-64.

- 1,196
- 9
- 17
-
1As a side-note: all of the listed above are applicable to externally linked functions, and functions that CAN be externally called (a pointer to function is taken somewhere in the unit). If a compiler (I'm speaking of x86 MSVC, but it may be extended to others) can deduce that the function is linked only internally (within single compilation unit - o/obj) AND it also considers it a less overhead by not inlining one, it is free in how it assigns registers / stack slots to arguments. – Arty Dec 05 '18 at 19:04
Neither Standard C nor Standard C++ has such a concept - these are features of specific compilers, linkers and/or operating systems, so you should really indicate which specific technologies you are interested in.
-
1Considering the tags, I think he refered to Microsoft Visual C++ – Cătălin Pitiș Jun 04 '09 at 11:19
-
3
-
Oh, so that's why I didn't understand why C++ syntax suddenly allowed for this extra type to be shoved in between the return type and the function name? It's not actually a part of ordinary C++ syntax? – Kyle Delaney Jun 24 '17 at 16:02
-
3Although K&R C had a `fortran` keyword reserved for this, which no compiler ever used. – Davislor Jul 04 '17 at 02:35
Standard C++ basically has two: extern "C"
and extern "C++"
. The latter is the default; this former used when you need to link to C code. Compilers may define other strings besides "C" and "C++". For instance, a compiler that's compatible with its Pascal sibling may define extern "Pascal".
Unfortunately, some compilers have invented keywords instead. In these cases, see the compiler documentation.

- 173,980
- 10
- 155
- 350
-
22
-
1Well, as you yourself mentioned, ISO C++ doesn't have a notion of "calling conventions", and doesn't exactly describe what linkage specifications are, either - only what you can do with them. So it's a grey areas basically. That's why I gave `extern "Pascal"` as an example. A compiler can certainly use a different register allocation scheme for functions with that linkage specification. – MSalters Jun 04 '09 at 11:31
-
The two concepts are distibct. Linkage specification have to do with naming, calling conventions have to do with stack arrangement etc. It is possible and reasonable to use the same linkage specification with two different calling conventions, or vice versa. – Jun 04 '09 at 11:53
-
6No, sorry, you're introducing a MSVC-centric view here. ISO definitely does NOT say that linkage specification is (just) naming. And one of the reasons that qsort() is overloaded on linkage is because on non-MSVC platforms the stack arrangements ("calling conventions") do differ between extern "C" and extern "C++". – MSalters Jun 04 '09 at 12:37
-
2Dunno why this was downvoted - linkage specification is certainly the only thing in standard C++ that can change calling conventions. – Johannes Schaub - litb Jun 04 '09 at 13:57
-
@Neil, it *has* to do with calling convention. You are not allowed to do this, for example: extern "C" void f(); int main() { void(*fp)() = &f; f(); } even though many compilers allow it, since they do not have different calling conventions for extern"C"/"C++", it can possibly change between those. in the code above, you would have to do: extern "C" typedef void(*fpec)(); int main() { fpec fp = &f; fp(); } - linkage is part of the function type. See this bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40336 – Johannes Schaub - litb Jun 04 '09 at 14:16
-
@MSalters, can you point me to the ISO specification that discusses the stack arrangement differences between extern "C" and extern "C++" ? – mrduclaw Oct 14 '09 at 09:07
-
@mrduclaw: No, because neither the ISO C not the ISO C++ specification discusses the existance of the stack itself, let alone how it's used. – MSalters Oct 14 '09 at 09:49
-
@MSalters, my bad, I understood your statement: "stack arrangements ("calling conventions") do differ between extern "C" and extern "C++"." to mean that stack arrangements between extern "C" and extern "C++" differ. And I guess I further understood since you were talking about ISO standards that the difference was probably defined somewhere and probably not random. – mrduclaw Oct 15 '09 at 01:51
-
5@anon extern "Pascal" and extern "C" are both linkage specifications AND calling convention specification. Or how else should the compiler know that the first function is to be called with Pascal calling conventions? Pascal usually pushs the arguments from right to left onto the stack and then the return address. The callee is clearing up the stack on return. C does usually exactly the opposite (due to possible variable length argument lists), pushing from left to right and the CALLER clears the stack as only he knows how many arguments he provided. – Angel O'Sphere Sep 03 '13 at 17:27
-
I would say that linkage specifications are calling convention _hints_, myself, rather than specifications. No linkage specification requires a specific convention; rather, they require a convention compatible with the specified linkage, and leave the choice of which one specifically up to the compiler. I would personally love it if there was a way to manually specify a specific convention as part of the language itself, maybe something like `extern "C++-gcc-cdecl"` and `extern "C++-ms-fastcall"`, or attributes like `[[gcc-cdecl]]` and `[[ms-fastcall]]`, on platforms that support them. – Justin Time - Reinstate Monica Jul 28 '19 at 18:29
These concern what order to put parameters on the call stack, and when to use call by value and/or call by reference semantics. They are compiler specific extensions intended to simplify multilingual programming.

- 98,632
- 24
- 142
- 234
They’re platform-specific extensions needed to call functions in certain libraries, particularly the Win32 API. They’re nonstandard and specific to each compiler, although MSVC’s options are the de facto standard for Windows on x86. Normally, a library that needs them will declare them in the header files and they will work transparently. The main difference between them is that C historically used a less-efficient convention that allowed for a variable number of arguments of any type, while Windows and most other languages did it differently. A lot of the differences, though, such as pushing left-handed or right-handed and having the caller or the called function clean up, were pretty arbitrary.
They’re largely irrelevant to 64-bit code: the holy wars over calling conventions never happened on those platforms.
There are a few common cases where you might need to add one of these to a function. A C++ module that needs to link with modules written in other languages (and sometimes even other C++ compilers) will have to use the extern "C"
naming convention for compatibility. A callback function needs to use the same calling convention as the caller, which with the Windows API is CALLBACK
, not the default. A shared library might need to export its functions with a different calling convention than it uses internally, or might want to make its use of __cdecl
explicit in case the default changes. You might or might not get better performance from __fastcall
on some platforms: it mostly speeds up short leaf functions with one or two parameters, and could make some programs slower.

- 14,674
- 2
- 34
- 49