0

I am reading a book for C and I got stuck into this example.

The author says that the result for this example will be x == 0 and y == 101.

I am fine with the y result,however I really thought that the first thing in the expression will calculate y == y and then will increment y +1.

I compiled the code and got a Warning: unsequenced modification and 1 was stored in x.

What's the reason for this?

int main(void)
{
    int x,y=100;
    x=y;
    x= y == y++;
    printf ("%d %d",x,y);
    return 0;
}
Spiros Gkogkas
  • 432
  • 5
  • 11
  • Well it's a book in my native language, it is called in english "The programming language C in depth (5th edition)" – Spiros Gkogkas Feb 20 '21 at 16:59
  • "Unsequenced modification" sounds like the warning Clang gives for that. Try the same with GCC. – ilkkachu Feb 20 '21 at 17:01
  • 'The programming language C in depth (5th edition)' - sounds like an instruction. Attach a heavy weight to the book and drop it in the deepest water you can get to. Challenger Deep would be good. – Martin James Feb 20 '21 at 17:18

2 Answers2

1

An expression in C, including a subexpression of another expression, may have two effects:

  • A main effect: It produces a value to be further used in the containing expression.
  • A side effect: It modifies an object or file or accesses a volatile object.

In general, the C standard does not say when the side effect occurs. It does not necessarily occur at the same time that the main effect is evaluated.

In x = y == y++;, y++ has the side effect of modifying y. However, y is also used as the left operand of ==. Because the C standard does not say when the side effect will occur, it may occur before, during, or after using the value of y for the left operand.

A rule in the C standard says that if using the value of an object is not sequenced (specified to occur before or after) relative to a modification of that object, the behavior is undefined. Also, if two modifications are unsequenced relative to each other, the behavior is undefined.

An original motivation for this rule is that increment y for y++ could require multiple steps. In a computer with only 16-bit arithmetic, a C implementation might support a 32-bit int by using multiple instructions to get the low 16 bits of y, add 1 to them, remember the carry, store the resulting 16 bits, get the high 16 bits of y, add the carry, and store the resulting bits. If some other code is separately trying to get the value of y, it might get the low 16 bits after the 1 has been added but get the high 16 bits before the carry has been added, and the result could be a value of y that is neither the value before the add (e.g., 0x1ffff) nor the value after the add (e.g.&, 0x20000) but a mix (0x10000). You could say an implementation ought to track operations on objects and keep them separate so this interleaving does not occur. However, that can impose a burden on compilers and interfere with optimization.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Are multi-word variables really the motivation for leaving that undefined? There doesn't seem much reason for the compiler to stick accesses to another variable in the middle of incrementing one. On the other hand, it would be entirely plausible for a compiler to compile `x++ == y` into the straightforward "get value of `x`, increment `x`, get value of `y`, compare", without regard to if `x` and `y` were in fact the same variable. And for another to punt the increment to the end of whole expression. – ilkkachu Feb 20 '21 at 17:06
  • @ilkkachu: If the issue were merely that `x` and `y` were different names for the same object (which could occur if a routine were passed pointers `p` and `q` and had the expression `(*p)++ == *q`), then we would not need a rule that the behavior is undefined, just that it is unspecified whether the value for `y` (`*q`) is the value before or after the increment. It is the fact that modifications to objects may be non-atomic that motivates us to go further than unspecified to undefined. – Eric Postpischil Feb 20 '21 at 19:02
1

In the expression y == y++ the order in which the expressions y and y++ are evaluated is unsequenced or, in simpler terms, the order is not specified.

However, here the result depends on the order in which the expressions are evaluated. Therefore the compiler emits a diagnostic.

koder
  • 2,038
  • 7
  • 10