4

I am trying to understand how this code works,

int main () {
 int m, k;
 m = (k=5)+(k=8)+(k=9)+(k=7);
 printf("m=%d\n",m);
 printf("k=%d\n",k);
}

The output: m=32 k=7

I have no idea how is the value of m become 32. I hope someone can help me to understand how this code works and how the outputs end up like this

Abhijith Ea
  • 115
  • 11
  • 1
    C or C++? The answers will be different. – Yksisarvinen May 20 '21 at 10:59
  • Also in case of C++ the language version matters. – Lundin May 20 '21 at 11:01
  • @Lundin `+` operands are unsequenced in all versions. – molbdnilo May 20 '21 at 11:04
  • warnings are your friend: "warning: multiple unsequenced modifications to 'k'" – Shlomi Agiv May 20 '21 at 11:04
  • Anyway, I'll simply down vote and close vote as unclear until the question is edited into shape with the incorrect language tags removed. Feel free to @Lundin me when it is fixed and I'll retract them. I've lost all patience with these cross-tagging questions. Kindly read the tag usage wiki of a tag before using it. Kindly make an effort to know what programming language you are coding in before you start coding. – Lundin May 20 '21 at 11:06
  • This code is ugly, don't write in this way. – prehistoricpenguin May 20 '21 at 11:06
  • @molbdnilo False. + is sequenced from let to right (left associativity), but evaluation order of subexpressions is undefined. – Jean-Baptiste Yunès May 20 '21 at 11:06
  • 2
    @Jean-BaptisteYunès: Associativity is not sequencing. Per C 2018 5.1.2.3 3, sequencing is defined as ordering on evaluations of expressions. It is nonsensical to say something is sequenced but evaluation order of subexpressions is undefined: Sequencing is specifying evaluation order. – Eric Postpischil May 20 '21 at 11:07
  • @Yksisarvinen i used c here – Abhijith Ea May 20 '21 at 11:08
  • @EricPostpischil 1.9 Program execution note 9 say exactly the converse a+b+c is evaluated as (a+b)+c. What is undefined is the order with which a, b and c subexpressions are evaluated. If not associativity would means nothing at all. – Jean-Baptiste Yunès May 20 '21 at 11:13
  • if you run (k=5) the out put is 5. so m = (k=5)+(k=8)+(k=9)+(k=7) means m=5+8+9+7 that is 32 ; and in the last value of k is 7. – Rsvay May 20 '21 at 11:14
  • Careless talk. Prefer to say that `a + b + c` is *grouped* as `(a + b) + c`. You can't say what is *evaluated* when, since there are no sequencing points in the expression. – Bathsheba May 20 '21 at 11:14
  • 1
    @Jean-BaptisteYunès: Neither the C standard nor the C++ standard has a clause 1.9. I have no idea what your “1.9 Program execution note 9” refers to. `a+b+c` is **structured** as `(a+b)+c`. That does not tell us how it is evaluated. – Eric Postpischil May 20 '21 at 11:15
  • @EricPostpischil: I quite like that term *structured*. I wonder where I get my term *group* from? By the way, I second all your comments. – Bathsheba May 20 '21 at 11:16
  • *Can anyone explain how this happened?* The **C** programming language is not a nanny language. It presumes that the programmer knows what they're doing, and doesn't prevent them from doing bad things like buffer overruns or multiple unsequenced modifications or egregious cavalier casting. – Eljay May 20 '21 at 11:17
  • @EricPostpischil a = a + 32760 + b + 5; the expression statement behaves exactly the same as a = (((a + 32760) + b) + 5); due to the associativity and precedence of these operators. Thus, the result of the sum (a + 32760) is next added to b, and that result is then added to 5 which results in the value assigned to a. On a machine in which overflows produce an exception and in which the range of values representable by an int is [-32768,+32767], the implementation cannot rewrite this expression as a = ((a + b) + 32765); – Jean-Baptiste Yunès May 20 '21 at 11:17
  • @Jean-BaptisteYunès: no, no, no. *structuring* (*grouping*?) are different things entirely from the algebraic concept of what gets added to when. – Bathsheba May 20 '21 at 11:18
  • 1
    @Jean-BaptisteYunès: So? The **value** computations of the operands of an operator are sequenced before the value computation of the result of the operator. But the **side effects** are not. Neither `a + b + c` nor `(a + b) + c)` imposes any ordering on the side effects of the operands. `+` is not “sequenced” to impose any ordering on these side effects. The side effects in `a`, `b`, and `c` may be performed in any order or even intermingled, and those are the computations that are at issue in this question. – Eric Postpischil May 20 '21 at 11:20
  • 1
    @Eljay In all fairness, the standard could have mandated a certain order of evaluation but it didn't. Supposedly it's an old argument of compiler/executable speed vs language usefulness. C chose to be less useful in favour of performance. Rational language designers could also simply have made it a constraint violation to write multiple side effects on the same variable in the same expression. This would have made the language safer and cost nothing. But C wasn't rationally designed. – Lundin May 20 '21 at 11:22
  • @Bathsheba Uh? C17 5.1.2.3 Note 15 Example 6. Order is explicitly stated, otherwise computation may not lead to consistent results (intermadiate trap representations). What I missed? – Jean-Baptiste Yunès May 20 '21 at 11:22
  • 1
    @EricPostpischil intermediate results may lead to wrong computation. – Jean-Baptiste Yunès May 20 '21 at 11:24

3 Answers3

4

Simplified explanation:

When you use k=... multiple times in the same expression, all assignments to that same variable are so-called "unsequenced side-effects". Simply put, it means that C doesn't specify which operand of + to evaluate/execute first nor does it specify the order in which the assignments will get carried out.

So the compiler has no way of knowing which k to evaluate/assign to first and therefore gets all confused. This is so-called "undefined behavior", anything can happen.

You have to solve this by splitting the expression up in several, each separated by a semicolon, which acts as a "sequence point", meaning all prior evaluations need to be done at the point where the ; is encounterd. Example:

k=5;
k+=8;
k+=9;
m = k + 7;

Detailed explanation with standard references here: Why can't we mix increment operators like i++ with other operators?

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    This is the only *sensible* answer so far. – Bathsheba May 20 '21 at 11:21
  • There is no `+=` in the question, and `k +=` does not express any intent evident in the question. Code aligned with the apparent intent would be `m = k = 5; m += k = 8; m += k = 9; m += k = 7;`. – Eric Postpischil May 20 '21 at 11:22
  • @EricPostpischil This is one way out of many to re-write the original code in a well-defined manner. – Lundin May 20 '21 at 11:23
  • @Lundin Thank you, Now i understood the flaw's in code. it was my first time submitting a question in stack overflow, so i forgot to pay attention to the tags i used at fisrt. – Abhijith Ea May 20 '21 at 12:11
1

This is undefined behavior. Your compiler warn about this

warning: multiple unsequenced modifications to 'k' [-Wunsequenced]

You can learn more about this here:

Smit Shah
  • 108
  • 11
0

The behaviour of the program is undefined.

There are multiple unsequenced writes on k in the expression

(k = 5) + (k = 8) + (k = 9) + (k = 7)
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • @EricPostpischil: I'm starting to think this too. I'll ask the community. – Bathsheba May 20 '21 at 11:27
  • `...5, k)` isn't sequenced with `+ (k = ...)` so it is still UB. If you want to use comma as abominable "sequence point padding", it will have to be `(0,k=5) + (0,k=8)` or some such. – Lundin May 20 '21 at 11:27
  • subexpressions evaluation is not ordered, adding a sequence point in subexpressions doesn't change the "global" behaviour of subexpressions evaluation order. – Jean-Baptiste Yunès May 20 '21 at 11:29
  • @EricPostpischil Here it is: https://stackoverflow.com/questions/67619477/is-a-0-a-a-1-a-undefined-behaviour – Bathsheba May 20 '21 at 11:30
  • (comments above relate to a previous version of this answer, hopefully to be cleared up with my question). – Bathsheba May 20 '21 at 11:31
  • @Lundin, Above my pay grade - I've asked the community. – Bathsheba May 20 '21 at 11:31