C函数调用无括号

这是一个简单的C程序:

#include  int main(void) { printf("Display something\n"); fflush stdout; return 0; } 

使用msys2 mingw-w64 gcc版本7.3.0和选项-Wall进行编译,一切正常,就好像第5行是fflush(stdout);

我试图用我自己的函数重现这样的调用,但是我得到了完全预期的错误

 src/main.c: In function 'int main(int, char**)': src/main.c:5:18: error: expected ';' before 'parameter' custom_function parameter; ^~~~~~~~~ 

那么, fflushfunction会发生什么? 有人可以解释一下吗? 你和其他C编译器有相同的行为吗?

让我们看看预处理器输出(使用MinGW和gcc -E test.c命令行):

  fflush # 5 "test.c" 3 (&(* _imp___iob)[1]) # 5 "test.c" ; 

如你所见, stdout是一个用括号扩展为(&(* _imp___iob)[1])的宏。

所以编译器使用这些括号,语法没问题。

但这只是因为宏观魔法,以及大多数宏受括号保护以避免与其他令牌产生副作用的事实(例如运算符优先)

你可以使用这个简单的代码重现那个没有任何包含:

 #define arg ("hello") void f(const char *x) { } int main(int argc, char** argv) { f arg; return 0; } 

当然这是不好的做法,混淆IDE(和人类),所以就是不要这样做。

你的问题:

在此处输入图像描述

参见Jean-FrançoisFabre的回答。 标准中的措辞有些奇怪(我并没有声称它不仅仅是那个)。

C99 7.19.1说:

标头声明了三种类型,几个宏,以及许多用于执行输入和输出的函数。

宏是

stderr stdin stdout

它是“指向FILE的指针”类型的表达式,它们分别指向与标准错误,输入和输出流相关联的FILE对象。

正如Keith Thompson早就说过的那样,在上下文中,这表示它们是宏 – 但是所有其他宏的描述都使用了“扩展为”的短语。 对于stderr,stdin和stdout,它表示它们表达式(如果它们是宏,则不是严格正确的)。

如果允许它们是声明的对象而不是宏,那么应该更改7.19.1p1以允许这些声明,并且stderr,stdin和stdout的描述不应该是页面长度运行的一部分 – 一句话。

更合理的是,如果要求它们宏,则应将“哪些是表达式”改为“扩展为表达式”。

它们不保证是宏。 在你的情况下,你很幸运宏扩展到带有保护括号的表达式。 隐藏实际内容的邪恶宏观的纯粹例子。