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

huangapple go评论100阅读模式
英文:

Using comma operator (a, b) when a is a block of code

问题

#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;
}

显示结果

result = 10

我正在使用gcc中的默认C版本。这个特性是特定于gcc吗?我知道(a, b)返回b,但我没有预料到当a是一个{}块时也会起作用。有人能解释为什么它起作用以及为什么必须用括号括起来才能使其起作用吗?

编辑:这是我试验的一个简化的#define的例子。一位程序员的评论(谢谢)解释了这一点。问题解决了。

英文:
#include &lt;stdio.h&gt;

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

    return 0;
}

displays

result = 10

I'm using whatever the default version of C is in gcc. Is it specific to gcc? I'm aware (a, b) returns b but I didn't expect to get it to work when a was a {} block. Can anyone explain why it works and why the block has to be bracketed to get it to work?

EDIT: This is a contrived simplified example of a #define I was trying out. Some programmer dude's comment (thanks) clears it up. Case closed.

答案1

得分: 5

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

目前默认版本是-std=gnu17,等同于“带有GNU扩展的宽松ISO C17”。这不是符合标准的模式,不建议给初学者使用。

> 这是特定于gcc吗?

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

> 我知道(a,b)返回b,但当a是一个{}块时,我没有预期它会起作用。

逗号运算符具有特殊的评估规则,保证子表达式ab之前完全评估。通常情况下,C运算符不会这样。这意味着您可以假设在a中的所有内容在b之前执行,甚至可以安全地包含使用b的代码。

但是,要初始化的变量列表不具有这样的顺序保证。int sum = 0, result=sum;不保证任何特定的顺序或顺序 - 这样的代码非常有问题,可能是未定义的行为。


最佳实践是尽可能遵循标准C,编写尽可能可读的代码,并避免定义不清晰的行为。复杂的“一行代码”是非常不好的实践。因此,这个代码可以更好地编写成:

int sum = 0;
for (int i=0; i < 5; i++) 
{
  sum+=i;
}
int result = sum;

或者如果您更喜欢,100%等效的写法:

int result = 10;
英文:

> I'm using whatever the default version of c is in gcc.

Currently that's -std=gnu17, equivalent to "lax ISO C17 with GNU extensions". It is not a conforming mode and not recommended for beginners.

> Is it specific to gcc?

Yes, or rather it is specific to the GNU C dialect, which is at least partially supported by clang as well. As mentioned in comments, this is a non-standard extension known as "statement expressions" or "statements in expressions". It allows multiple expressions/lines and optionally returns a value like a function-like macro.

> I'm aware (a, b) returns b but I didn't expect to get it to work when a was a {} block

The comma operator has a special evaluation rule guaranteeing that the sub-expression a is fully evaluated before b. Normally this isn't the case with C operators. This means that you can assume that everything at a is executed before b and you may even safely include code using b.

However, a list of variables to be initialized does not come with such a sequencing guarantee. int sum = 0, result=sum; does not guarantee any particular order or sequencing - code such as this is deeply problematic and possibly undefined behavior.


Best practices are to follow standard C whenever possible, to write code as readable as possible and to avoid poorly-defined behavior. Complex "one-liner" code is very bad practice. So this would have been much better written as:

int sum = 0;
for (int i=0; i &lt; 5; i++) 
{
  sum+=i;
}
int result = sum;

Or if you prefer, the 100% equivalent:

int result = 10;

huangapple
  • 本文由 发表于 2023年8月9日 18:26:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866848.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定