这是一个简单的C程序:
#include <stdio.h>
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;
^~~~~~~~~
那么,fflush
函数会发生什么?有人可以解释一下吗?你和其他C编译器有相同的行为吗?
答案 0 :(得分:13)
让我们看看预处理器输出(使用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(和人类),所以就是不要这样做。
答案 1 :(得分:0)
你的问题:
见Jean-FrançoisFabre的回答。 在措辞中有一个奇怪的地方 标准(我没有声称它不仅仅是那个)。
C99 7.19.1说:
正如Keith Thompson很久以前所说的那样 在上下文中,这表示它们是宏 - 但是所有的描述 其他宏使用短语“扩展为”。对于stderr, stdin和stdout,它说他们是表达式(如果他们是的话) 宏,并不严格正确。)标题声明了三种类型,几个宏和 许多用于执行输入和输出的功能。
...
宏是
...
stderr的 标准输入 标准输出
是指向“指向FILE的指针”类型的表达式 FILE对象分别与标准错误相关联, 输入和输出流。
如果他们被允许,比如声明对象而不是宏, 然后应该更改7.19.1p1以允许这些声明,和 stderr,stdin和stdout的描述不应该是 一页长期的连续判决。
更合理的是,如果他们 需要是宏,那么短语“哪个 表达式“应该更改为”,扩展为表达式“。
不保证它们是宏。在你的情况下, 你很幸运,宏扩展到带有保护括号的表达式。 隐藏实际内容的邪恶宏观的一个纯粹例子。