C 中带括号的奇怪语法

问题描述 投票:0回答:4

我得到了代码:

#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 syntax parentheses
4个回答
1
投票
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


1
投票

在这个表达语句中

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) 逗号运算符是从左到右计算的。


1
投票

确定其工作原理有两个步骤:

表达方式:

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


0
投票

它是 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。

© www.soinside.com 2019 - 2024. All rights reserved.