在什么版本的C中,括号内的块用于返回有效值?

在什么版本的C中,括号内的块用于返回有效值?,c,C,如果我这样做: int j = ({int x = 7; x+3;}); 在i686-apple-darwin10-gcc-4.2.1(gcc)4.2.1(apple Inc.build 5646)gcc中,它编译得很好。有问题的块({int x=7;x+3;})返回最后一条语句的值作为块的值。如果删除括号,则它不会编译。我能指望这在大多数C编译器中正常工作吗 此外,此构造的名称是什么?我在搜索它时遇到了很多麻烦,因为搜索引擎没有索引()或{},而C是一个糟糕的搜索词。我也没有在我的任何一本书

如果我这样做:

int j = ({int x = 7; x+3;});
在i686-apple-darwin10-gcc-4.2.1(gcc)4.2.1(apple Inc.build 5646)gcc中,它编译得很好。有问题的块
({int x=7;x+3;})
返回最后一条语句的值作为块的值。如果删除括号,则它不会编译。我能指望这在大多数C编译器中正常工作吗


此外,此构造的名称是什么?我在搜索它时遇到了很多麻烦,因为搜索引擎没有索引
()
{}
,而C是一个糟糕的搜索词。我也没有在我的任何一本书中找到关于它的任何东西,可能是因为我不知道该找什么。

你可以期待它在大多数GCC版本中都能工作

您可以期望它在其他任何地方都能工作——它是一个GCC扩展

GCC手册中描述该功能的部分标题为“表达式中的语句和声明”:

括号中的复合语句可能在GNU C中显示为表达式

后来它说:

在语句表达式中的语句中创建的任何临时变量都将被销毁 在声明末尾。这使得宏中的语句表达式稍微复杂一些 与函数调用不同

因此,“语句表达式”似乎是文档中使用的名称

如果删除括号,则它不会编译

如果没有括号,编译器会将其视为聚合初始化块,并在看到
int
关键字时失败。初始值设定项块中不能有关键字

6.7.8初始化

11标量的初始值设定项应为单个表达式,可以选择用大括号括起来。这个 对象的初始值是表达式的初始值(转换后);同一类型 简单赋值的约束和转换适用,采用标量的类型 为其声明类型的非限定版本

6.2.5类型

21算术类型和指针类型统称为标量类型。数组和 结构类型统称为聚合类型


我能指望这在大多数c编译器中正常工作吗

不,看起来像是一个非标准的GNU扩展

此外,此构造的名称是什么

我不知道有没有。实际上,这与宏通常所做的类似

这是一个:

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

回想一下,复合语句是由大括号包围的语句序列;在此构造中,括号围绕大括号。例如:

 ({ int y = foo (); int z;
    if (y > 0) z = y;
    else z = - y;
    z; })
对于
foo()
的绝对值,是一个有效的(尽管比必要的稍微复杂)表达式

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


请不要期望它能够工作,也不要期望人们能够阅读您的代码。clang似乎也支持这一点。为了与GCC兼容,clang支持GCC支持的大多数东西。当然,这并不意味着使用它是个好主意。你必须选择它是否合理。我只是在陈述事实。叮当声不是“几乎不存在”的。对于使用它是否是一个好主意,没有主观评论。在这个问题上,Clang只是“伪装的GCC”——尽管内部完全不同。如果不是因为GCC支持它,我不确定Clang会不会支持它,尽管这充其量只是一个半知情的猜测,而且由于它是受支持的,所以无法验证任何一种方式。AFAIAC,它仍然是一个GCC扩展。你是否决定使用它取决于你自己。我已经编码了30年没有陈述式的表达,在接下来的30年里没有特别的计划去使用它,但是在必要的时候,会考虑什么是合适的。