英文:
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 <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;
}
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是一个{}块时,我没有预期它会起作用。
逗号运算符具有特殊的评估规则,保证子表达式a
在b
之前完全评估。通常情况下,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 < 5; i++)
{
sum+=i;
}
int result = sum;
Or if you prefer, the 100% equivalent:
int result = 10;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论