标准 C 函数声明语法 (WINAPI)

The standard C function declaration syntax (WINAPI)

我知道您可能认为这个问题已经得到解答,但事实并非如此,或者至少我不是很清楚。

int WINAPI WinMain (){}

这是著名的 winmain 函数的伪形式。

我的问题是关于调用约定 WINAPI特别是它在 "return type" 和 "function name" 之间的位置 。这是标准C吗?因为我参考了 Brian W. Kernighan 和 Dennis M. Ritchie 的书,但我没有看到这个表格。

我也搜索过它的意思,他们说这是一个宏来代替_stdcall。所以请不要告诉我这个问题是重复的。

这是一个可能与我非常接近的问题 What does "WINAPI" in main function mean?

我想要一个明确的答案WINAPI它是标准的 C 语言吗? 所以我可以在 return 类型之后放置一个调用约定函数声明,然后我将它交给世界上的 any C 编译器?或者它是否只适用于 Microsoft 编译器?如果是这样,任何人都可以将他们的规则强加于 C 语法吗?

很抱歉,我知道我的问题对你们中的许多人来说可能微不足道,但我到处搜索函数声明语法,所有来源都拒绝了这个调用约定的地方。

您明确问题的答案:

WINAPI, Is it a standard C?

不是。__stdcall是 Microsoft 扩展。

__stdcall 和关键字的位置都是 Microsoft 特定的。任何编译器供应商都能够在其实现中添加非标准语法。

this MSDN 文章的最顶部:

Microsoft Specific

它还在页面末尾提到了 WINAPI 宏:

In the following example, use of __stdcall results in all WINAPI function types being handled as a standard call: [...]`

这种形式适用于 Microsoft C++ 编译器和 MinGW 工具链,它为 Windows 实现了 GCC。

但一般来说,GCC 使用它的属性来使用这种其他形式:

int WinMain() __attribute__((stdcall)) // or WINAPI if using the macro
{}

不过,将来我们有可能通过使用最近的 C++11 generalized attributes 比如.

[[ms::stdcall]]
int WinMain() {}

事实上,GCC and Clang 都已经支持标准通用属性作为编译器特定属性语法的替代。

WINAPI 是在 windows.h 中定义的宏,扩展为 __stdcallwindows.h__stdcall 都是 Windows 特定的——没有任何行业标准定义它们含义的任何方面。

C 和 C++ 标准确实定义了对函数定义具有相关影响的关键字:inline_Noreturn (C2011) 和 static。所有这些关键字通常都放在 之前 return 类型,但如果我正确阅读 C2011,语法实际上并不要求这样做:你完全可以写

int static foo(void) { return 42; }

这些关键字称为函数说明符存储class说明符。 不要将它们与type specifierstype qualifiers混淆,它们也可以出现在这个位置,但是修改return 当他们这样做时键入

基本答案:否。C 语言标准定义的函数声明在 return 类型和函数名称之间没有元素。所以 int __bootycall myFunc(int qux) 不是标准 C(或 C++),即使 C 实现允许保留 __customIdentifiers 供自己独占使用。

但是

调用约定说明符(例如 __cdecl)的需求很明确;许多(尤其是早期的非 UNIX [尤其是 MS-DOS])平台有不止一种调用约定可供选择,并且指定函数的调用约定与参数列表一样重要,甚至更重要那个功能。因此需要在其中插入一些额外的东西。

当时(甚至在 C89 之前),没有为特定于体系结构的函数属性做出规定(大概是因为 C 设计的唯一目的是实现 UNIX 实用程序,不需要任何)。这稍后会在 C99 中得到补救,如果 C99 在那时已经存在,那么 __cdecl 等人很可能。应该是函数属性,而不是随机标识符。但事实上,当需要指定非默认调用约定时,有四个合理的地方可以放置它:return 类型之前,return 类型和函数名称之间,函数名和参数列表的左括号,以及参数列表之后。

我在这里推测,但似乎第二种选择最有意义。请记住,这是 C++ 之前的版本;没有 post-arglist-const,唯一可以出现在 return 类型之前的是 static,它指定了链接而不是任何东西 about 函数本身。留在函数名称之前或之后,并将函数名称与其参数列表分开会降低可读性。这在 return 类型和函数名称之间留下了一个稍微不寻常的位置,作为坏一堆中最好的。

剩下的就是历史了。后来的编译器利用新生的 __attribute__ 语法将调用约定关键字放在更合适的位置,但是基于 DOS 的编译器(其中 Microsoft C 是第一个)将它推到 return 之后类型。