在什么版本的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年里没有特别的计划去使用它,但是在必要的时候,会考虑什么是合适的。