What do you mean by this? Like writing to a specific integer address?
*((volatile unsigned *)(0x20001000)) = 0x12345678;
That's not UB and is also the only way to write to memmapped registers.What do you mean by this? Like writing to a specific integer address?
*((volatile unsigned *)(0x20001000)) = 0x12345678;
That's not UB and is also the only way to write to memmapped registers.It is, however, not the only way to write to memmapped registers.
The original C way of doing so was to use an assembly function wrapping the actual act of reading/writing (honestly, better than doing the above, as it helps making it very explicit how the write will happen as well as abstracting any details like needing to add a barrier or whatsoever), the other way was to specify the symbol with address of the memmapped register in assembly, and link resulting object with C code.
A C implementation is, AFAIK, free to refuse the literal addresses used as pointers and pass as ISO C.
At least they don't without LTO.
What I mean is, most compilers won't generate a function call or an additional indirect memory access for *(111) = 222;, unlike your spec-compliant alternatives.
This is, IMO, the problem. Sometimes we just want a more ergonomic way than inline assembly in a hot loop (and also we'd like to to pretend its portable). The spec does not have an answer to this.
So, unless all C compilers in the world actively sabotage this usage (like how Go did to map traversal orders), your spec saying this is "implementation defined" have no impact at all. All C compilers are bound to implement the same intuitive but completely-not-enforced-by-spec behavior. Because if they don't, people just use something else.
Please cite chapter and verse of the C standard which defines this behavior. Any edition.
Edit: Looks like the result in this case is implementation defined: https://stackoverflow.com/a/24212940