| ▲ | tsimionescu an hour ago | ||||||||||||||||||||||||||||||||||||||||||||||
Your first paragraph makes it sound as if the compiler will actually generate two reads of the value of some register, which might lead to unexpected effects at runtime for certain special registers. However, this is not at all what UB means in C (or C++). The compiler is free to optimize away the entire block of code where this printf() sequence occurs, by the logic that it would be UB if the program were to ever reach it. For example, the following program:
Can be optimized to always print "y is 8" by a perfectly standard compliant compiler. | |||||||||||||||||||||||||||||||||||||||||||||||
| ▲ | shakna an hour ago | parent [-] | ||||||||||||||||||||||||||||||||||||||||||||||
"volatile" tells the compiler it is _not_ safe to optimise away any read or write, so it can't just optimise that section away at all. > An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3. Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously. A compliant compiler is only free to optimise away, where it can determine there are no side-effects. But volatile in 5.1.2.3 has: > Accessing a volatile object, modifying an object, modifying a file, or calling a function that does any of those operations are all side effects. | |||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||