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

时间:2011-06-17 15:38:57

标签: 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;
}

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

4 个答案:

答案 0 :(得分:7)

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

为什么需要这个的明显例子是通常的max宏:

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

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

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

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

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

答案 1 :(得分:4)

这称为statement expression,不是标准ISO的一部分,但GCC支持它。

从手册中引用:

  

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

     

...

     

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

答案 2 :(得分:4)

它是一个名为statement expressions的GCC扩展名。

一条建议:

每当您看到这种奇怪的语法时,都必须尝试使用​​-pedantic选项进行编译。如果语言规范支持,您将立即知道。

例如,我使用-pedantic选项编译它,并说,

  

警告:ISO C ++禁止在表达式

中使用支撑组

答案 3 :(得分:0)

我很确定这不是有效的C ++。 C ++标准的第5章定义了 表达式 是什么。 FOO(val)确定因为地狱不是表达式。因此,int a = FOO(6);无效