__stdcall
和__cdecl
调用约定规定函数名称必须以下划线开头:
C(__ cdecl)
同样的限制适用于32位世界和16位世界。 参数从右向左推(所以第一个 参数离堆栈顶部最近,并且调用者清除 参数。 函数名称由前导下划线装饰。
__ STDCALL
这是用于Win32的调用约定,但有例外 可变函数(必然使用__cdecl)和极少数 使用__fastcall的函数。参数从右推到 左[纠正上午10:18],被叫方清理堆栈。 功能 名称由前导下划线和尾随@ -sign装饰 后跟函数采用的参数字节数。
我在Visual C ++中编译了以下代码(源文件有.c
扩展名,所以我猜源文件编译为C
文件:
void __stdcall stdcallFunction(int i)
{
int j = 12345;
}
void __cdecl cdeclFunction(int i)
{
int j = 12345;
}
int main()
{
stdcallFunction(123);
cdeclFunction(123);
return 0;
}
我注意到编译对象文件中的函数名称没有前导下划线:
__stdcall
和__cdecl
调用约定的函数名称的前导下划线是可选的吗?
答案 0 :(得分:1)
功能装饰不是C标准的一部分。
它是由所使用的开发环境定义的ABI(抽象二进制接口)中定义的内容。
具体而言,问题中报告的规则是MS使用的规则。
MS编译器默认情况下不使用C修饰(修改),除非函数包含在EXTERN 'C' { ... }
块中,或者使用了特定的编译器开关(通常为-TC
)。 / p>
并且,正如另一个答案中已经提到的,64位代码的MS ABI使用不包含下划线前缀的不同C修改。
答案 1 :(得分:0)
名称修饰与调用约定没有直接关系。对于调用约定,调用者和被调用者使用相同的约定非常重要,如果在声明中提供正确的属性,编译器可以确保它们可以。
因此名称装饰只是传统。有时可以推断出如何从其装饰名称中调用函数。因此,在从库中公开函数时遵循约定是一种很好的做法。我假设如果您dllexport
这些函数并将代码链接到DLL中,您最终会得到装饰名称。