这个陈述是如何评估的,这是什么叫做?

jos*_*sec 9 c gcc

#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;
}
Run Code Online (Sandbox Code Playgroud)

我试图围绕上面的例子.FOO宏如何以及为什么工作(最后一个语句似乎作为返回值)?就语法而言,所调用的各个部分是什么以及其他规则适用于什么?

Bli*_*ndy 7

这是使用GCC非标准扩展来允许来自代码块的返回值,主要用于宏.代码块中的最后一个值被视为"返回值".

需要这个原因的一个明显例子是通常的max宏观:

#define max(a,b) (a)<(b)?(b):(a)
Run Code Online (Sandbox Code Playgroud)

调用max(new A(), new B())会导致分配3个对象,而实际上你只需要2个(设想的例子,但是其中一个操作数被评估两次).

使用此扩展程序,您可以改为:

#define max(a,b) ({ typeof(a) _a=(a); typeof(b) _b=(b); _a<_b?_b:_a; })
Run Code Online (Sandbox Code Playgroud)

在这种情况下,两个操作数都只被评估一次,就像一个函数一样,但具有宏的所有好处(例如它们).


Mic*_*man 4

这称为语句表达式,不是标准 ISO 的一部分,但 GCC 支持它。

引用手册:

括在括号中的复合语句可能在 GNU C 中显示为表达式。这允许您在表达式中使用循环、开关和局部变量。

...

复合语句中的最后一项应该是一个表达式,后跟一个分号;该子表达式的值用作整个构造的值。