我最近看到一段C代码,包括以下样式的宏:
#define TOTO() \
do { \
do_something(); \
do_another_something(); \
} while (0)
我起初想知道do while (0)
在这里的目的,但是this answer向我解释:如果宏只是在if
或{{1}后使用的话没有大括号,像这样:
else
所以在这里,如果没有if (something)
TOTO();
else
do_something_else();
语句,代码将扩展为:
do while (0)
哪种语法错误,因为if (something)
do_something();
do_another_something();
else
do_something_else();
不再直接跟随else
范围。
但是我认为它可以通过在自己的范围内声明宏而没有必要的if
,所以我用大括号测试了相同的代码。我的整个代码如下所示:
do while
但是GCC给了我以下错误:
错误:'else'没有先前的'if'
但是,#include <stdio.h>
#define HELLO_WORLD() \
{ \
printf("hello "); \
printf("world!\n"); \
}
int main(int argc, char** argv)
{
if (argc == 1)
HELLO_WORLD();
else
fprintf(stderr, "nope\n");
return 0;
}
函数的代码应扩展为:
main
哪个有效。
那我在这里错过了什么?
答案 0 :(得分:9)
宏观之后的分号。
将宏扩展为此:
if (argc == 1)
{
printf("hello "); \
printf("world!\n"); \
};
else // HERE, SYNTAX ERROR
fprintf(stderr, "nope\n");
return 0;
由于if
- 语句的正文和else
- 子句之间不应有分号,因此语法错误。
OTOH,do
- while
循环允许(并且需要)分号。
只需打印真实的预处理器输出,就可以轻松避免对编译器输出的误解。这可以通过使用
来实现-E
可执行文件的gcc
开关。来自man 1 gcc
:-E 在预处理阶段后停止;不要运行编译器 正确。输出采用预处理源代码的形式, 它被发送到标准输出。
cpp
可执行文件。 谢谢
- @dhke用于纠正错误发生的行。
- @kakeh提供预先查看预处理器输出的建议。
答案 1 :(得分:2)
仔细查看您如何调用宏。
你必须写
if (argc == 1)
HELLO_WORLD() // NO SEMICOLON!!!!!!!
else
fprintf(stderr, "nope\n");
这将是一种神经质,因为你永远不能用真实函数替换HELLO_WORLD宏。