2

I was given the code:

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

and my task was to figure out how it works. I do not understand how the line

c = (a -= a - 5), (a = b, b + 3); 

works, though.

My guess is that it works just like this code:

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

because the result is the same.

But I don't understand the first version of the code. So firstly, it changes the value of a (a becomes 5), then changes the value of c (c becomes a), and then it performs the expression in the second parentheses (which seems to not affect the value of c at all, although it's the same line of code and there was no semicolon in between, only a comma. what is that syntax? Is there a name for that kind of syntax? i just don't understand why it was written like that and why it does what it does.

Also, less importantly, what does the line:

b + 3;

do? Is it just nothing?

4
  • Search for the comma operator. Commented Apr 25, 2024 at 9:27
  • "My task was to figure out how it works": the task of the person who gave you this task should have been to fire the person who wrote this garbage. Commented Apr 25, 2024 at 10:09
  • The b + 3 line is a no-op — most compilers will remove it (certainly if any optimization is used; probably even without optimization). Commented Apr 25, 2024 at 15:52
  • I removed the How does the comma operator work and what precedence does it have? duplicate because it is tagged C++ and some of its answers discuss overloading the comma operator, which is wholly inapplicable to C. Commented Apr 25, 2024 at 15:57

4 Answers 4

4

There are two steps of determining how it works:

The expression:

c = (a -= a - 5), (a = b, b + 3); 

= bonds more tightly than ,. It is parsed as:

( c = ( a -= (a - 5) ) ) , ( (a = b) , (b + 3) ); 

The , comma operator is first and executes left operand first. The result of the comma operator is equal to the right operand. See https://en.cppreference.com/w/c/language/operator_other#Comma_operator .

So first c = ( a -= (a - 5) ). On assignment = the both sides are "unsequenced" with each other, can be in any order. But in these cases, like a vs a - 5, nothing fancy happens on the left side of =. The result of assignment is the assigned value. See https://en.cppreference.com/w/c/language/operator_assignment .

Bottom line, the order of operation will be:

 ( 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

With a small caveat that 1. and 2. operations are actually unsequenced. a maybe evaluated before a - 5, which doesn't change anything. Calculating, we will get:

   ( 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

The resulting assignment result will be: c = 5, a = 0 and the expression "returns" the value 3.

what is that syntax?

Comma operator is most probably confusing here.

what does the line b + 3; do? is it just nothing?

Yes, it does nothing.

Sign up to request clarification or add additional context in comments.

Comments

3
c = (a -= a - 5), (a = b, b + 3);

It is equivalent to:

a -= a - 5;
c = a

and

int temp = a - 5;
a -= temp;
c = a;

So c is equal to 5

Why?

Because you have two operators

c = (a -= a - 5), (a = b, b + 3);
^^^^^^^^^^^^^^^^  **************
      1st               2nd

The second part of the second one is simply no-op and is ignored by the compiler

If you wanted the whole comma to be evaluated, then you need to use another pair of parenthesises:

    c = ((a -= a - 5), (a = b, b + 3));
    //  ^                            ^ 

and the result will be 3.

1 Comment

Re "Because you have two operators", The things you identified as operators are actually operands (of a , operator) and thus expressions, but they are not operators.
2

In this expression statement

c = (a -= a - 5), (a = b, b + 3);

there is used the comma operator. As the assignment operator has a higher priority than the comma operator then the above expression statement may be equivalently rewritten like

( c = (a -= a - 5) ), (a = b, b + 3);

So you are right saying that the statement may be split into these statements

a -= a - 5;
c = a;
a = b;
b + 3;

Pay attention to that the expression b + 3 has no effect because its value is not used and discarded.

And one more the original expression statement also may be equivalently rewritten without using any parentheses like

c = a -= a - 5, a = b, b + 3;

because 1) the assignment operator is evaluated from right to left and 2) the comma operator is evaluated from left to right.

One important remark about the comma operator: there is a sequence point between evaluations of operands of the comma operator. So for example you may write

int a = 0;

++a, a++, ++a, a++;

After execution this statement a will be equal to 4.

Comments

0

It's the C comma operator. From Wikipedia:

the comma operator (represented by the token ,) is a binary operator that evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type).

Also note that the comma operator has the lowest precedence of any C operator including assignment.

So in the line

c = (a -= a - 5), (a = b, b + 3)

The comma operator has the lowest precedence of all C operators so it first evaluates c = (a -= a - 5) and discards the result (NB the assignments change a and c as a side effect).

Then it evaluates a = b, b + 3 and returns the result of that. This expression contains a comma operator of its own, so a = b is evaluated and the result discarded (although the assignment "sticks" because it is a side effect). Then it evaluates b + 3 and returns the result which is also the return result of the entire expression, but the result of the entire expression is discarded.

i just don't understand why it was written like that

It's just an exercise. You'll rarely see a line of code like that in the wild, and if you do, alarm bells should be ringing because that code is sure to be full of WTFery.

NB the comma operator is defined to include a sequence point between the evaluation of its two operands. So the fact that a is assigned in both parts does not induce undefined behaviour.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.