#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宏如何以及为什么工作(最后一个语句似乎作为返回值)?就语法而言,所调用的各个部分和其他规则适用于什么?
答案 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);
无效