__stdcall和__cdecl调用约定的函数名称的前导下划线是可选的吗?

时间:2017-08-10 06:21:10

标签: c calling-convention

__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;
}

我注意到编译对象文件中的函数名称没有前导下划线:

enter image description here

__stdcall__cdecl调用约定的函数名称的前导下划线是可选的吗?

2 个答案:

答案 0 :(得分:1)

功能装饰不是C标准的一部分。

它是由所使用的开发环境定义的ABI(抽象二进制接口)中定义的内容。

具体而言,问题中报告的规则是MS使用的规则。

MS编译器默认情况下不使用C修饰(修改),除非函数包含在EXTERN 'C' { ... }块中,或者使用了特定的编译器开关(通常为-TC)。 / p>

并且,正如另一个答案中已经提到的,64位代码的MS ABI使用不包含下划线前缀的不同C修改。

答案 1 :(得分:0)

名称修饰与调用约定没有直接关系。对于调用约定,调用者和被调用者使用相同的约定非常重要,如果在声明中提供正确的属性,编译器可以确保它们可以。

因此名称装饰只是传统。有时可以推断出如何从其装饰名称中调用函数。因此,在从库中公开函数时遵循约定是一种很好的做法。我假设如果您dllexport这些函数并将代码链接到DLL中,您最终会得到装饰名称。