将括号括起来的块放在期望表达式的位置的C ++语法是什么?


78

我遇到了这个奇怪的C ++程序。

#include <iostream>
using namespace std;
int main()
{
  int a = ({int x; cin >> x; x;});
  cout << a;
}

谁能解释发生了什么?这个结构叫做什么?


51
它被称为“混淆代码”
2011年

2
@VJo:我的意思是,这个“({})”结构叫什么?它类似于匿名函数吗?
Koshimitsu

1
+1 Blimey,我以前从未见过。太糟糕了,它是特定于GNU C / C ++的……
sehe 2011年

1
+1,看起来有点像lambda函数:)
iammilind

18
是我一个人,还是gcc中比其他任何编译器都更多的bizarro非标准扩展?
David Heffernan

Answers:


68

它将用户输入值分配给a并打印出来。这是通过使用来完成的Statement Expression

C / C ++标准不支持gnu gcc编译器扩展的语句表达式。因此,任何使用语句表达式的代码都不符合标准且不可移植。

IBM IBM XL C / C ++ v7.0也支持Statement Expressions,它的文档恰当地解释了它们:

语句表达式:

复合语句是用大括号括起来的一系列语句。在GNU C中,括号内的复合语句可能作为表达式出现在所谓的中Statement expression

         .--------------.
         V              |
>>-(--{----statement--;-+--}--)--------------------------------><

语句表达式的值是出现在整个构造中的最后一个简单表达式的值。如果最后一条语句不是表达式,则该构造的类型为void并且没有值。

总是选择在GCC一个sandard编译代码,使用其中的一个选项-ansi-std=c90-std=iso9899:1990-std=c++03-std=c++0x; 要获得该标准所需的所有诊断,还应该指定-pedantic(或者-pedantic-errors如果您希望它们是错误而不是警告)


56

这是GCC扩展程序。编译的代码-pedantic,如果你想摆脱这样的东西(你真的标志想)。


10
我怀疑它获得了如此多的选票,因为许多人在得知他们从未听说过或使用过的东西不是标准后就松了一口气。
Blagovest Buyukliev 2011年

18

它创建一个内联作用域,x在其中声明,从标准输入中读取它,然后整个语句最终计算为x,并分配给a

逗号运算符的工作原理类似,尽管它不需要单独的作用域。例如:

int x;
int a = (cin >> x, x);

会做同样的事情。所有与逗号连接的语句将顺序执行,整个表达式的结果将设置为最右边的操作数的值。


“({})”有什么具体名称吗?
Koshimitsu 2011年

@Koshimitsu:没有,因为它是运算符的组合(如果您想称呼它们的话)。在这种情况下,大括号{}定义范围的开始({)和结束(})。常规括号就可以封装范围的定义和返回值。我不确定在这种情况下是否可以省略这些常规括号,但是我希望可以。
Rycul 2011年

1
@Koshimitsu:我对C ++不太熟悉,但是在C语言中这是完全合法的,并且我已经使用了很多次。
Blagovest Buyukliev 2011年

1
@Neil:好吧,也许是因为gcc是我使用的唯一C编译器,因此我误导了我。
Blagovest Buyukliev 2011年

13

我不认为这是标准的C ++。它可能是特定于编译器的扩展,它允许内部范围求值。


1
@Doc:废话。首先,这不是标准C。我不知道它可能已经添加到C ++ 0x中。
奥利弗·查尔斯沃思

13
@Doc你误会了。它不是标准的C ++,也不是标准的C。它是GCC扩展,称为“语句表达式”。
Johannes Schaub-litb 2011年

我不相信是这样。Visual Studio当然不会接受它。
小狗

3
@mathepic:GCC显然不是(没有正确的选择),因此这里的问题和困惑...
rubenvb 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.