在ANSI C中,复合语句(块)是否被parens表达式包围?

在ANSI C中,复合语句(块)是否被parens表达式包围?,c,gcc,standards,expression,C,Gcc,Standards,Expression,浏览Linux内核源代码时,我发现用括号括起来的语句块被视为一个表达式a la lisp(或ML),即一个值为最后一条语句值的表达式 例如: int a = ({ int i; int t = 1; for (i = 2; i<5; i++) { t*=i; } t; }); 它被称为“表达式中的大括号组” 不允许ANSI/ISOC,也不允许C++,但GCC支持它。 < P>这不是标准C。它是GCC扩展名。您可以找到C扩展的完整列表

浏览Linux内核源代码时,我发现用括号括起来的语句块被视为一个表达式a la lisp(或ML),即一个值为最后一条语句值的表达式

例如:

int a = ({
    int i;
    int t = 1;
    for (i = 2; i<5; i++) {
        t*=i;
    }
    t;
});
它被称为“表达式中的大括号组”


不允许ANSI/ISOC,也不允许C++,但GCC支持它。

< P>这不是标准C。它是GCC扩展名。您可以找到C扩展的完整列表。这实际上是其中之一,虽然文档中没有明确命名,但它看起来像

正如您所观察到的,最后一个表达式用作表达式的值,文档中说(强调我的):

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

主要的好处之一是制作安全的宏,避免对参数进行多次求值,从而产生副作用。给出的示例使用此不安全的宏:

#define max(a,b) ((a) > (b) ? (a) : (b))
它对
a
b
求值两次,可以使用如下语句表达式重写以消除此问题:

#define maxint(a,b) \
   ({int _a = (a), _b = (b); _a > _b ? _a : _b; }) 
注意,需要显式使用
int
,这可以使用另一个
gcc
扩展来修复:


请注意,

是否有可能写出一个宏,像没有声明表达式那样安全?”FLIMM,我不这么认为,但我不认为自己是一个宏观专家。我尽可能地避免它们,尽管有些情况下它们很难避免,例如滚动您自己的断言。@Flimm这取决于您希望宏执行的操作,在某些情况下,当然可以编写安全的宏。对于完整的
max
功能,无论您在标准C中做什么,您都会在某些方面出现不足-问题是您要么需要知道参数的类型,要么必须对其中一个参数求值两次(后者是上述宏方法的问题)。Hmpf,最后一个应该修改以正确支持异类参数。您可以通过将
\uuuuuu extension\uuuuu
放在左括号之前来抑制GCC中的警告。@Flimm为什么这不是答案?
\uuuuuu extension\uuuu
有帮助,但在全局范围内使用该语句时没有帮助scope@hellow:因为它不能解决问题;上面只是墙纸。
#define maxint(a,b) \
   ({int _a = (a), _b = (b); _a > _b ? _a : _b; }) 
#define max(a,b) \
   ({ typeof (a) _a = (a), _b = (b); _a > _b ? _a : _b; })