在我的C++代码中,"#define __cdecl"的含义是什么?

4

我正在使用Visual Studio处理一个已有的C++项目,发现几乎每个函数声明都在函数名前面加了__cdecl,例如:void __cdecl functionName()。然后我跳转到winnt.h文件中查看__cdecl的定义:

#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define NTAPI __stdcall
#else
#define _cdecl
#define __cdecl
#define NTAPI
#endif

我搜索了cdecl,发现它是C和C++程序的默认调用约定,但上面的代码告诉我__cdecl没有扩展到任何内容。那么为什么在函数名前放置__cdecl,因为它什么也不代表吗?还是我误解了上面的代码?

1
编译器处理__cdecl声明。它不是(也不能)在语言中定义,因此该宏为空。 - Konrad Rudolph
看到那个 #if 和它的条件了吗?如果条件为真,编译器可能会将它们作为扩展关键字。 - Some programmer dude
1
微软编译器使用__cdecl作为调用约定。对于其他编译器,它可以定义为空。 - Bo Persson
这个答案中的URL重定向到https://learn.microsoft.com/en-us/cpp/cpp/cdecl?redirectedfrom=MSDN&view=msvc-170 - 但是编辑队列已满,我无法更新它。 - AJM
32位代码有多种调用约定,__stdcall是另一种常见的约定。您找到了它的64位定义,x64是一个干净的设计,不再区分cdecl和stdcall。这就是为什么#define为空的原因。 - Hans Passant
2个回答

1
“#define __cdecl”的含义是什么?
以“#”开头的行是预处理器指令。 “#define”是一个指令,用于定义预处理宏。 “#define __cdecl”定义了一个带有标识符“__cdecl”的宏和空替换。如果定义了这样的宏,处理器将替换所有实例的“__cdecl”为空字符串。
那么为什么在函数名之前放置__cdecl,因为它什么也不是吗?
看一下所讨论的定义开头的指令:
#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#else
该宏定义具有条件性。当该宏未被定义时,__cdecl 将不会扩展为空。如果未扩展为空,则 __cdecl 是一个微软特定的函数说明符,正如您所发现的那样。
有条件地定义宏允许编写使用 __cdecl 的代码在允许其存在的系统上运行,并自动在不支持的系统上删除它。
“#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)”是预处理器指令,用于测试宏 _MSC_VER 是否具有大于 800 的值,或者宏 _STDCALL_SUPPORTED 是否被定义。如果测试结果为假,则 #if 和 #else 之间的代码将被删除。如果测试结果为真,则 #else 和 #endif 之间的代码将被删除。

我了解了,所以这是在特定条件下注释__cdecl的方法。但我仍然困惑于#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)这一行,它是什么意思? - Mengfan Ma
1
@Mark:_MSC_VER 只由 Microsoft Visual C 编译器定义,并包含其版本号。这是一个检查是否在 Microsoft 编译器(版本 8 或更高版本)上进行编译,或者一个声明 _STDCALL_SUPPORTED 的编译器的方法。它们将使用 __stdcall__cdecl;其他编译器则不会。 - DevSolar

0

这意味着,如果一个API被定义为使用NTAPI,它将生成使用__stdcall调用约定的代码 - 这是Pascal调用约定的一种变体,在其中被调用者清除堆栈。而对于__cdecl,调用者清除堆栈(因此它支持可变参数类型函数)。

所有这些都取决于#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)的条件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接