开发者

How is this statement evaluated and what is this kind of thing called?

#define FOO(val) \
({                                              \
   int b = val开发者_如何学编程;                                 \
   printf("First, let's count to %d\n", val);   \
   for (int i = 1; i <= val; i++) {             \
      printf("%d...\n", i);                     \
   }                                            \
   b++;                                         \
   b;                                           \
})

int main() {
   int a = FOO(6);
   printf("a=%d\n", a);

   a = (4);     // straightforward, everyone should be familiar with this
   a = (4;);    // does not compile
   a = { 4; };  // does not compile
   a = ({ 4;}); // valid, a will equal 4


   return 0;
}

I'm trying to wrap my head around the above example. How and why does the FOO macro work (the last statement appears to act as a return value)? As far as syntax goes, what are the individual parts called and what other rules apply?


That's using a GCC non-standard extension to allow return values from code blocks, mostly intended for macros. The last value inside a code block gets treated as a "return value".

A clear example of why this was needed is the usual max macro:

#define max(a,b) (a)<(b)?(b):(a)

Calling max(new A(), new B()) causes 3 objects to be allocated, when in fact you only want 2 (contrived example, but the point is one of the operands gets evaluated twice).

With this extension you can instead write:

#define max(a,b) ({ typeof(a) _a=(a); typeof(b) _b=(b); _a<_b?_b:_a; })

In this case both operands get evaluated exactly once, just like a function, but with all benefits of macros (such as they are).


This is called a statement expression, and is not a part of standard ISO, however GCC supports it.

Quoting from the manual:

A compound statement enclosed in parentheses may appear as an expression in GNU C. This allows you to use loops, switches, and local variables within an expression.

...

The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct.


Its a GCC extension called statement expressions.

One advice:

Whenever you see such weird syntax, must try compiling it with -pedantic option as well. You will immediately know, if its supported by the language specification or not.

For example, I compiled it with -pedantic option, and it says,

warning: ISO C++ forbids braced-groups within expressions


I am pretty sure this isn't valid C++. Chapter 5 of the C++ standard defines what an expression is. FOO(val) sure as hell is not an expression according to that. Therefore, int a = FOO(6); is invalid

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜