ANSI C 中的复合语句(块)是否被括号表达式包围?

发布于 2024-07-30 11:46:36 字数 673 浏览 3 评论 0原文

浏览Linux内核源代码我发现一些片段代码,其中括号括起来的语句块被视为表达式 a la lisp(或 ML),即,其值是最后一个语句的值的表达式。

例如:

int a = ({
    int i;
    int t = 1;
    for (i = 2; i<5; i++) {
        t*=i;
    }
    t;
});

我一直在查看 ANSI C 语法 试图弄清楚这段代码如何适合解析树,但我还没有成功。

那么,有人知道这种行为是标准强制的还是只是 GCC 的一个特性?

更新:我尝试过使用 -pedantic 标志,编译器现在给了我一个警告:

warning: ISO C forbids braced-groups within expressions

Browsing the Linux kernel sources I found some piece of code where a block of statements surrounded by parenthesis is treated as a expression a la lisp (or ML), that is, an expression which value is the value of the last statement.

For example:

int a = ({
    int i;
    int t = 1;
    for (i = 2; i<5; i++) {
        t*=i;
    }
    t;
});

I've been looking at the ANSI C grammar trying to figure out how this piece of code would fit in the parse tree, but I haven't been successful.

So, does anybody know if this behaviour is mandated by the standard or is just a peculiarity of GCC?

Update: I've tried with the flag -pedantic and the compiler now gives me a warning:

warning: ISO C forbids braced-groups within expressions

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

刘备忘录 2024-08-06 11:46:36

这不是标准的 C。它是一个名为 语句表达式 的 gcc 扩展。 您可以在此处找到 C 扩展的完整列表。 这实际上是 Linux 内核中使用的许多 gcc 扩展之一似乎 clang 也支持这个尽管文档中没有明确命名。

正如您所观察到的,最后一个表达式充当表达式的值,文档中写道(强调我的):

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

主要好处之一是制作可以避免多次求值的安全宏具有副作用的参数。 给出的示例使用了这个不安全的宏:

#define max(a,b) ((a) > (b) ? (a) : (b))

它计算 ab 两次,并且可以使用语句表达式重写以消除此问题,如下所示:

#define maxint(a,b) \
   ({int _a = (a), _b = (b); _a > _b ? _a : _b; }) 

注意,需要显式使用int 可以使用另一个 gcc 扩展来修复 Typeof

#define max(a,b) \
   ({ typeof (a) _a = (a), _b = (b); _a > _b ? _a : _b; }) 

请注意 clang 也支持typeof。

This is not standard C. It is a gcc extension called statement expressions. You can find the complete list of C extensions here. This is actually one of the many gcc extensions used in the Linux kernel and it seems like clang supports this too and although it is not explicitly named in the document.

As you observed the last expression serves as the value of the expression, the document says (emphasis mine):

The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct. (If you use some other kind of statement last within the braces, the construct has type void, and thus effectively no value.)

One of the main benefits would be to make safe macros that would avoid multiple evaluations of arguments with side effects. The example given uses this unsafe macro:

#define max(a,b) ((a) > (b) ? (a) : (b))

which evaluates either a or b twice and can be rewritten to eliminate this problem using statement expressions as follows:

#define maxint(a,b) \
   ({int _a = (a), _b = (b); _a > _b ? _a : _b; }) 

Note, the need to explicitly use int which can fixed using another gcc extension Typeof:

#define max(a,b) \
   ({ typeof (a) _a = (a), _b = (b); _a > _b ? _a : _b; }) 

Note that clang also supports typeof.

本王不退位尔等都是臣 2024-08-06 11:46:36

它被称为“表达式内的支撑组”。

ANSI/ISO C 和 C++ 都不允许这样做,但 gcc 支持它。

It's called "braced-group within expression".

It's not allowed by ANSI/ISO C nor C++ but gcc supports it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文