如何用C ++编译“({expr1; expr2;})”?

时间:2014-05-22 21:31:54

标签: c++ gcc syntax

我曾经使用但从未理解的东西是C ++编写代码的能力:

#include <stdio.h>

void sideEffect()
{
    printf("Hello, I'm a side effect\n");
}

int main()
{
    printf(({sideEffect(); "Hello side effect\n";}));
    return 0;
}

打印:

Hello, I'm a side effect
Hello side effect

({ expr1; expr2; })部分似乎运行块并用最后一个值'替换'整个事物。

这只是我没有得到的运算符优先级的结果,还是还有其他事情发生?

更新

一些非显而易见的事情(至少对我而言)是最后一个表达式被复制,即使它正在返回一个引用。我添加了一个简单的Foo类,当它被复制到上面的例子时打印出来:

...

struct Foo
{
    Foo()
    {}
    Foo(const Foo&)
    {
        printf("Copying Foo...\n");
    }
};

const Foo& getFoo()
{
    static Foo f;
    return f;
}

int main()
{
    const Foo& foo = ({sideEffect(); getFoo();});
    return 0;
}

输出:

Hello, I'm a side effect
Copying Foo...

如果Foo是不可复制的,则无法编译

2 个答案:

答案 0 :(得分:8)

这是GCC实现的C和C ++语言的扩展。它被称为Statement Expressions

我将从下面的文档中复制一下:

  

回想一下,复合语句是由大括号包围的一系列语句;在这个结构中,括号围绕括号。例如:

({ int y = foo(); int z;
   if (y > 0) z = y;
   else z = - y;
   z;
})
     

是foo()的绝对值的有效(虽然稍微复杂一点)表达式。

     

复合语句中的最后一件事应该是一个后跟分号的表达式;此子表达式的值用作整个构造的值。 (如果你在大括号中最后使用了一些其他类型的语句,那么构造的类型为void,因此实际上没有值。)

正如海湾合作委员会的文件所述,它经常用于宏:

#define maxint(a,b) \
   ({int _a = (a), _b = (b); _a > _b ? _a : _b; })

答案 1 :(得分:0)

您看到的是两个不同的PrintF调用,这就是为什么它们在两个单独的行上显示的原因。程序进入时

printf(({sideEffect(); "Hello side effect\n";}));

它将立即调用sideEffects方法,该方法随后将调用新的唯一printF语句

printf("Hello, I'm a side effect\n");

但是,由于sideEffects没有返回(void),因此它不会对原始printF语句产生任何影响,只在输出中留下字符串文字“Hello side effect \ n”。