我得到了代码:
#include <stdio.h>
int main(void) {
int a = 0, b = 0, c = 0;
c = (a -= a - 5), (a = b, b + 3);
printf("a = %d, b = %d, c = %d", a, b, c); // a = 0, b = 0, c = 5
}
我的任务是弄清楚它是如何工作的。我不明白怎么行
c = (a -= a - 5), (a = b, b + 3);
但是有效。
我的猜测是它的工作原理就像这段代码:
#include <stdio.h>
int main(void) {
int a = 0, b = 0, c = 0;
a -= a - 5;
c = a;
a = b;
b + 3;
printf("a = %d, b = %d, c = %d", a, b, c); //a = 0, b = 0, c = 5
}
因为结果是一样的。
但是我不明白第一个版本的代码。所以首先它改变a的值(a变成5),然后改变c的值(c变成a),然后执行第二个括号中的表达式(这似乎根本不影响c的值,虽然是同一行代码,中间没有分号,只有一个逗号,这种语法有什么名称吗?我只是不明白为什么要这样写以及为什么这样做。它有什么作用。
另外,不太重要的是,这行代码是什么:
b + 3;
做什么?难道就没什么吗?
c = (a -= a - 5), (a = b, b + 3);
它相当于
a -= a- 5;
c = a
和
int temp = a -5;
a -= int;
c = a;
C 等于 5
为什么?
因为你有两个操作员
c = (a -= a - 5), (a = b, b + 3);
^^^^^^^^^^^^^^^^ **************
1st 2nd
第二部分的第二部分只是无操作,会被编译器忽略
如果您想要评估整个逗号,那么您需要使用另一对括号:
c = ((a -= a - 5), (a = b, b + 3));
// ^ ^
结果将是
3
。
在这个表达语句中
c = (a -= a - 5), (a = b, b + 3);
使用了逗号运算符。由于赋值运算符的优先级高于逗号运算符,因此上面的表达式语句可以等效地重写为
( c = (a -= a - 5) ), (a = b, b + 3);
所以你说的是对的,该语句可以分为这些语句
a -= a - 5;
c = a;
a = b;
b + 3;
注意表达式
b + 3
没有任何效果,因为它的值没有被使用并被丢弃。
另外,原始表达式语句也可以等效地重写,而无需使用任何括号,例如
c = a -= a - 5, a = b, b + 3;
因为 1) 赋值运算符是从右到左计算的,2) 逗号运算符是从左到右计算的。
确定其工作原理有两个步骤:
表达方式:
c = (a -= a - 5), (a = b, b + 3);
=
紧密粘合。解析为:
( c = ( a -= (a - 5) ) ) , ( (a = b) , (b + 3) );
,
逗号运算符在前,首先执行左操作数。逗号运算符的结果等于右侧操作数。请参阅 https://en.cppreference.com/w/c/language/operator_other#Comma_operator .
所以首先
c = ( a -= (a - 5) )
。在分配时=
,双方彼此“无序”,可以是任何顺序。但在这些情况下,比如 a
与 a - 5
,=
的左侧不会发生任何奇特的事情。赋值的结果就是被赋值的值。请参阅 https://en.cppreference.com/w/c/language/operator_assignment .
底线,操作顺序为:
( c = ( a -= (a - 5) ) ) , ( (a = b) , (b + 3) )
1. a - 5 Evaluating right side of =
2. a Evaluating the left side of - when doing -=
3. a -= Assignment to a
4. c = Assignment to c
5. b Evaluating right side of =
6. a = Assignment to a
7. b + 3 Evaluating just the value b + 3
从全零开始,我们将得到:
( c = ( a -= (a - 5) ) ) , ( (a = b) , (b + 3) )
1. 0 - 5 = -5
2. \= 0
3. a = (0) - (-5) = 5
4. c = 5
5. 0
6. a = 0
7. 0 + 3 = 3
生成的赋值结果将是:
c = 5, a = 0
并且表达式的值为 3
。
它是 C 逗号运算符。来自维基百科:
逗号运算符(由标记
表示)是一个二元运算符,它计算第一个操作数并丢弃结果,然后计算第二个操作数并返回该值(和类型)。,
另请注意,逗号运算符的优先级是所有 C 运算符(包括赋值)中最低的。
所以这条线
c = (a -= a - 5), (a = b, b + 3)
逗号运算符在所有 C 运算符中具有最低优先级,因此它首先计算
c = (a -= a - 5)
并丢弃结果(注意,赋值会更改 a
和 c
作为副作用)。
然后它评估
a = b, b + 3
并返回结果。该表达式包含自己的逗号运算符,因此会计算 a = b
并丢弃结果(尽管赋值“粘住”,因为它是副作用)。然后它计算 b + 3
并返回结果,该结果也是整个表达式的返回结果,但整个表达式的结果被丢弃。
我就是不明白为什么要这样写
这只是一个练习。您很少会在野外看到这样的代码行,如果您看到了,那么应该敲响警钟,因为该代码肯定充满了 WTFery。