当 a 是代码块时使用逗号运算符 (a, b)

NoC*_*nde 4 c gcc gcc-statement-expression

#include <stdio.h>

int main()
{
    int sum = 0, result = (({for (int i = 0; i < 5; i++) sum += i;}), sum);
    
    printf("result = %d\n", result);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

显示

result = 10
Run Code Online (Sandbox Code Playgroud)

我正在使用 gcc 中 C 的默认版本。它特定于 gcc 吗?我知道(a, b)回报b,但我没想到它会在阻塞时发挥a作用{}。谁能解释它为什么起作用以及为什么必须将块括起来才能使其起作用?

#define编辑:这是我正在尝试的一个人为的简化示例。一些程序员的评论(谢谢)澄清了这一点。案件结案。

Lun*_*din 5

我正在使用 gcc 中 c 的默认版本。

目前-std=gnu17,相当于“带有 GNU 扩展的宽松 ISO C17”。这不是一种符合标准的模式,不推荐初学者使用。

它特定于 gcc 吗?

是的,或者更确切地说,它特定于 GNU C 方言,clang 也至少部分支持它。正如评论中提到的,这是一个非标准扩展,称为“语句表达式”或“表达式中的语句”。它允许多个表达式/行,并可选择返回一个值,如类似函数的宏。

我知道 (a, b) 返回 b 但我没想到当 a 是一个 {} 块时它会起作用

逗号运算符有一个特殊的求值规则,保证子表达式a在 之前被完全求值b。通常,C 运算符不会出现这种情况。这意味着您可以假设 at 的所有内容a都已在之前执行b,您甚至可以安全地使用 包含代码b

然而,要初始化的变量列表不具有这样的排序保证。int sum = 0, result=sum;不保证任何特定的顺序或排序 - 诸如此类的代码存在严重问题并且可能存在未定义的行为。


最佳实践是尽可能遵循标准 C,编写尽可能可读的代码并避免定义不明确的行为。复杂的“一行”代码是非常糟糕的做法。所以这本来可以更好地写成:

int sum = 0;
for (int i=0; i < 5; i++) 
{
  sum+=i;
}
int result = sum;
Run Code Online (Sandbox Code Playgroud)

或者,如果您愿意,也可以使用 100% 等效的:

int result = 10;
Run Code Online (Sandbox Code Playgroud)

  • @IanAbbott:我问了一个单独的问题:/sf/ask/5380736161/ 特定于C语言,这种行为似乎是在 C++ 中完全定义的。 (2认同)