将逗号分隔的多个整数分配给 C 中的一个 int - 为什么这样做有效?做什么的?

Assigning multiple integers separated by comma to an int in C - Why does that work? What for?

我在一次考试中看到了这个,当我尝试时,我感到很惊讶。我在网上试过,它也有效。所以我认为是C语言。

为什么有效?这种赋值语法的用例是什么?

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
    int i = (1,2,3,4,5);
    printf("%d", i);
    return 0;
}

这是工作中的逗号运算符。它计算左侧的表达式,创建一个序列点,丢弃表达式的值,然后计算右侧的表达式,并将 returns 作为值。当示例中有多个表达式时,将依次计算每个表达式,只保留最后一个。对于示例,编译器会进行评估,因为每个值在编译时都是已知的。请注意,函数的参数列表不是逗号运算符的使用。

这不是逗号运算符的有效用例。更接近有效的用例可能是一些具有副作用的操作(例如函数调用)需要排序并分配最终值:

int i = (getchar(), getchar(), getchar());

这会将 i 设置为标准输入中的第三个字符,如果标准输入中没有剩下三个字符可供读取,则设置为 EOF。仍然不是一个现实的用例,但比分配常量列表更好。

这些不是 "multiple integers",而是逗号运算符。整个括号内的部分是一个表达式,每个子表达式(用逗号分隔)严格从左到右计算。除了最右边的子表达式之外的所有结果都将被忽略。整个表达式的结果是最后一个(最右边)表达式的结果。这里是整数值5.

请注意,此运算符主要用于只允许单个表达式添加更多副作用的情况。例如。在一个循环中:

int cnt = 0;
for ( const char *cp = "Hello" ; *cp != '[=10=]' ; cp++, cnt++ )  ;

这会计算 C 字符串中的字符数,在每次迭代后递增指针和 cnt。此处忽略结果。

因此,这 没有 与元组或类似 Python 相关的方式。实际上,在任何情况下都无法避免使用此运算符,应谨慎使用 — 并且某些编码标准禁止使用它。

之所以有效,是因为您使用的是 "comma operator",它计算左侧和右侧的子表达式,并具有右侧表达式的值。

所以在(1,2,3,4,5)中,对1求值,结果被丢弃,然后2,3,4,5...其中(因为下一个逗号)2是评估并丢弃结果,然后 3,4,5... 其中 3 被评估并丢弃,然后 4,5... 其中 4 被评估并丢弃,然后 5 成为表达式的结果。

至于何时有用,主要是当您需要评估多个(子)表达式的副作用但对它们的值不感兴趣(可能最后一个除外)时的快捷方式。它有时在 for 循环表达式中很方便,例如递增两个变量时:

for (i=0,j=1; j < len; i++,j++) {

..它同时出现在初始化表达式和循环表达式中的位置。

除了其他答案之外,您还需要注意 , 是逗号运算符而不是分隔符的情况。例如,以下是无效的:

int i = 1,2,3,4,5;

在这种情况下,, 是变量声明之间的分隔符。它将 i 声明为 int 并将其初始化为 1,然后它尝试将 2 解析为变量名,但失败了。

Why is that working?

因为它是一个有效的 C 语法。 (1,2,3,4,5)中的逗号是逗号运算符

C11: 6.5.17 逗号运算符

Syntax
1 expression:

assignment-expression
expression , assignment-expression

Semantics
2 The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value.114)


What is the use case for such an assignment syntax?

参见下面的示例

3 EXAMPLE As indicated by the syntax, the comma operator (as described in this subclause) cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers). On the other hand, it can be used within a parenthesized expression or within the second expression of a conditional operator in such contexts. In the function call

f(a, (t=3, t+2), c)

the function has three arguments, the second of which has the value 5.