Her*_*man 2 c preprocessor inline-assembly
有这个代码:
#define GREATER(a, b, res) ( \ /* no braces here */
asm("cmp %1, %2\n\t" \
"jge 0f\n\t" \
"movl %1, %0\n\t" \
"jmp 1f\n" \
"0:\n\t" \
"movl %2, %0\n" \
"1:" \
: "=r"(res) \
: "r"(a), "r"(b)); )
Run Code Online (Sandbox Code Playgroud)
错误:
c.c:4:2: error: expected expression before ‘asm’
asm("cmp %1, %2\n\t" \
但是这个(只更改了大括号,其他所有内容都保留了 - 代码在其他方面是正确的):
#define GREATER(a, b, res) ({ \ /* used braces here - correct */
asm("cmp %1, %2\n\t" \
"jge 0f\n\t" \
"movl %1, %0\n\t" \
"jmp 1f\n" \
"0:\n\t" \
"movl %2, %0\n" \
"1:" \
: "=r"(res) \
: "r"(a), "r"(b)); })
Run Code Online (Sandbox Code Playgroud)
将编译没有错误。但唯一改变的是添加了大括号。那么为什么需要它们呢?预处理器假定语句是什么?(如果只是意味着在大括号中。)我已经看到其他只在括号中声明的宏函数(没有花括号),那么为什么这个函数应该有呢?
预处理器指令不涉及此问题。问题是:
asm(…)是 C 语言的 GCC 扩展。GCC 将asm, 后跟 a;视为一个语句。(…),括号的内容应该是表达式。因为asm不是表达式,(asm(…);)是错误。({…})具有类似于表达式的值,但可能包含语句。在里面({…}),你可以把语句放在大括号里面,GCC 会对它们求值,并使用其中最后一个表达式语句1的值作为({…})表达式的值。(in 的最后一个语句({…})应该是一个表达式语句,而不是其他类型的语句,就像一个for循环。)因此({ asm(…); })被接受为表达式。
然而,尽管 GCC 接受了它,但它违反了 GCC 文档中的声明“复合语句中的最后一件事应该是一个表达式,后跟一个分号……”。看起来您的宏并不打算用作表达式;它把结果放入res但本身没有价值。在这种情况下,您可以通过从原始代码中删除括号来使其成为一个简单的语句:
#define GREATER(a, b, res) \
asm("cmp %1, %2\n\t" \
"jge 0f\n\t" \
"movl %1, %0\n\t" \
"jmp 1f\n" \
"0:\n\t" \
"movl %2, %0\n" \
"1:" \
: "=r"(res) \
: "r"(a), "r"(b));
Run Code Online (Sandbox Code Playgroud)
此外,人们通常更喜欢;在此类宏中省略final ,因为这样在源代码中使用时,宏可以像语句一样编写:
GREATER(a, b, res);
Run Code Online (Sandbox Code Playgroud)
而不是对习惯于以以下结尾的语句的人来说很奇怪;:
GREATER(a, b, res)
Run Code Online (Sandbox Code Playgroud)
(虽然;在定义中,您仍然可以写GREATER(a, b, res);,但是这扩展为 have ;;,这可能会导致问题,因为由于额外的,if (foo) GREATER(a, b, res); else…将无法将其else与该相关联。)if;
1个甲语句表达式是一个表达式后跟一个;。