for*_*ran 37 c standards gcc expression
浏览Linux内核源代码时,我发现了一段代码,其中括号括起来的语句块被视为表达式a laisp(或ML),即表达式,其值是最后一个语句的值.
例如:
int a = ({
int i;
int t = 1;
for (i = 2; i<5; i++) {
t*=i;
}
t;
});
Run Code Online (Sandbox Code Playgroud)
我一直在研究ANSI C语法,试图弄清楚这段代码如何适合解析树,但我还没有成功.
那么,有没有人知道这种行为是由标准规定还是只是GCC的特殊性?
更新:我已尝试使用标志-pedantic,编译器现在给我一个警告:
warning: ISO C forbids braced-groups within expressions
Run Code Online (Sandbox Code Playgroud)
laa*_*lto 33
它被称为"表达式中的支撑组".
ANSI/ISO C和C++都不允许它,但gcc支持它.
Sha*_*our 32
这是无效的C它是一个gcc
名为语句表达式的扩展,你可以在这里找到完整的C扩展列表.这实际上是Linux内核中使用的许多gcc扩展之一,似乎clang也支持这一点,尽管它没有在文档中明确命名.
当你观察到最后一个表达式作为表达式的值时,文档说(强调我的):
复合语句中的最后一件事应该是一个后跟分号的表达式; 此子表达式的值用作整个构造的值.(如果你在大括号中最后使用了一些其他类型的语句,那么构造的类型为void,因此实际上没有值.)
其中一个主要好处是制作安全的宏,避免多重评估带有副作用的参数.给出的示例使用此不安全的宏:
#define max(a,b) ((a) > (b) ? (a) : (b))
Run Code Online (Sandbox Code Playgroud)
可以使用语句表达式重写其中一个a
或b
两个并重写以消除此问题,如下所示:
#define maxint(a,b) \
({int _a = (a), _b = (b); _a > _b ? _a : _b; })
Run Code Online (Sandbox Code Playgroud)
注意,需要明确使用int
哪个可以修复使用另一个gcc
扩展名Typeof:
#define max(a,b) \
({ typeof (a) _a = (a), _b = (b); _a > _b ? _a : _b; })
Run Code Online (Sandbox Code Playgroud)
请注意,clang也支持typeof.