Why an access to a volatile glvalue is considered a side effect by [intro.execution] ?

side-effect についてドラフトで再確認していたところ、その定義として “Reading an object designated by a volatile glvalue” という文面があったのでタイトルの内容をメモ。執筆時現在、side-effect については [intro.execution]/14/sentence-1 にて以下のように述べられている。

Reading an object designated by a volatile glvalue, modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment.


When a call to a library I/O function returns or an access through a volatile glvalue is evaluated the side effect is considered complete, even though some external actions implied by the call (such as the I/O itself) or by the volatile access may not have completed yet.

ライブラリ I/O 関数への呼び出しが返されるか、volatile glvalue によるアクセスが評価されると、呼び出しによって暗黙の外部操作(I / O自体など)や volatile なアクセスをまだ完了していない可能性がある。
stackoverflow にも分かりやすい回答が載っていたので一部引用。

Hardware registers, which is the normal use-case for volatile (typically in conjunction with pointers, but doesn't have to be), the read of a register will potentially have actual side-effects on the hardware - for example reading a fifo-register on a serial port [or network card, hard disk, or whatever], will affect the state of the hardware, since the fifo has now "moved on" one step. Skipping over, duplicating, caching the result of, or some other such optimisation would definitely cause a piece of driver code and hardware to behave in a different way than the programmer wanted - which would be the case if volatile wasn't considered as having a side-effect.