In this example, does correctness require global_value
to be declared volatile
?
int global_value = 0;
void foo () {
++ global_v
As Roland says, I'm not sure what part of the standard to cite to say, "if a program modifies something, that means the object is modified in the abstract machine. If a program uses a value, that means it uses whatever value the object has in the abstract machine".
volatile
controls the number and order of reads and writes to memory, but even without volatile
, an implementation that caches values as an optimization must respect the behavior of the abstract machine. That's what the "as-if" rule says, so optimizations that don't obey that aren't "easy to imagine" for me ;-) Your proposed emitted code is as clearly wrong to me as saying, "a write might go to memory without updating or dirtying the L1 cache, so future reads will still see the old value in the cache". Not on a single core, it won't, because a cache that behaved like that would be broken.
If you call strcpy
, and then examine the contents of the destination buffer, the compiler isn't allowed to "optimize" by using a prior value of that byte, stored in a register. strcpy
doesn't take a volatile char *
. Similarly, global_value
does not need to be volatile
.
I suppose the confusion may be that in multi-threaded code, "and then", which is to say whether the read occurs "after" the write and hence "sees" the new value, is defined by synchronization primitives. In some implementations, volatile
has something to do with synchronization due to implementation-specific guarantees.
In single-threaded code, and in the C and C++ standards, "and then" is defined by sequence points, of which there are plenty in the code given.