4

我正在使用 Visual Studio 开发一个现有的 c++ 项目,我发现几乎每个函数声明都__cdecl在函数名称前加上一个,例如:void __cdecl functionName(). 然后我跳转到__cdecl位于winnt.h文件中的 的定义:

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

我搜索了cdecl并得到它是 C 和 C++ 程序的默认调用约定,但上面的代码告诉我它__cdecl什么都没有。那么为什么要__cdecl在函数名称之前放置一个函数名,因为它什么都不是?还是我误解了上面的代码?

4

2 回答 2

1

#define __cdecl”是什么意思</p>

开头的行#是预处理器指令。#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 之间的代码。

于 2017-03-29T15:04:03.233 回答
0

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

而这一切都是有条件的#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)

于 2017-03-29T15:16:28.910 回答