Having this code:
#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)); )
Error:
c.c:4:2: error: expected expression before ‘asm’
asm("cmp %1, %2\n\t" \
But this one (only changed braces, everything else is left - the code is otherwise correct):
#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)); })
Will compile with no error. But the only changed is added braces. So why are they needed? What does the preprocessor assume to be statement? (If only means being in braces.) I have seen other macro functions declared only in parenthesis (no curly braces), so why this one should have ones?
The preprocessor directives are not involved in this issue. The issues are:
asm(…)
is a GCC extension to the C language. GCC treats asm
, which must be followed by a ;
, as a statement.(…)
, the contents of the parentheses should be an expression. Since asm
is not an expression, (asm(…);)
is an error.({…})
has a value like an expression but may contain statements. Inside ({…})
, you may put statements inside the braces, and GCC will evaluate them and use the value of the last expression statement1 in them as the value of the ({…})
expression. (The last statement in ({…})
should be an expression statement, as opposed to some other kind of statement, just as a for
loop.)Thus ({ asm(…); })
is accepted as an expression.
However, although GCC accepts it, it is violating the statement in GCC’s documentation that “The last thing in the compound statement should be an expression followed by a semicolon…”. It does not look like your macro is intended to be used as an expression; it puts a result in res
but does not itself have a value. In this case, you can make it simply a statement by removing the parentheses from your original code:
#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));
Additionally, people often prefer to leave off the final ;
in such macros, because then the macro can be written like a statement when used in source code:
GREATER(a, b, res);
instead of looking odd to people who are accustomed to statements ending with ;
:
GREATER(a, b, res)
(Although with the ;
in the definition, you can still write GREATER(a, b, res);
, but this expands to have ;;
, and that can cause problems, because if (foo) GREATER(a, b, res); else…
will fail to associate that else
with that if
because of the extra ;
.)
1 A statement expression is an expression followed by a ;
.