私はvolatiles
一般的には合理的な理解を持っているようですが、一見あいまいなケースが1つあり、標準に従ってどのように機能するのかわかりません。C99の関連部分とSOに関する12以上の関連記事を読みましたが、この場合のロジックまたはこの場合が説明されている場所が見つかりません。
次のコードがあるとします。
int a, c;
volatile int b;
a = b = 1;
c = b += 1; /* or equivalently c = ++b; */
a
次のように評価する必要があります。
b = 1;
a = b; // volatile is read
またはこのように:
b = 1;
a = 1; // volatile isn't read
?
同様に、次のc
ように評価する必要があります。
int tmp = b;
tmp++;
b = tmp;
c = b; // volatile is read
またはこのように:
int tmp = b;
tmp++;
b = tmp;
c = tmp; // volatile isn't read
?
物事のような単純なケースでa = b; c = b;
は明らかです。しかし、上記のものはどうですか?
基本的に、問題は、オブジェクトが揮発性である場合、C99の6.5.16c3で「式には割り当て後の左オペランドの値がある」とは正確には何を意味するのかということです。
代入演算子は、左のオペランドで指定されたオブジェクトに値を格納します。代入式には、代入後の左オペランドの値がありますが、左辺値ではありません。
代入式の値を生成するために、揮発性の余分な読み取りを意味しますか?
更新:
それで、ここにジレンマがあります。
「割り当て後のオブジェクトの値」が揮発性オブジェクトの追加読み取りから取得されない場合、コンパイラーは揮発性オブジェクトを次のように想定しますb
。
int
書き込まれる任意の値を保持できますが、そうではない場合があります(たとえば、ビット0は0に配線されています。これは、揮発性物質を使用することになっているハードウェアレジスタでは珍しいことではありません)。- 書き込みの割り当てが発生した時点と式の値が取得された時点の間で変更することはできません(これもハードウェアレジスタで問題になる可能性があります)
そして、そのすべてのために、式の値は、揮発性オブジェクトの追加の読み取りから取得されない場合、標準がそうであると主張している揮発性オブジェクトの値を生成しません。
これらの仮定は両方とも、揮発性オブジェクトの性質にうまく適合していないようです。
OTOH、「割り当て後のオブジェクトの値」が、上記の揮発性オブジェクトの追加の暗黙の読み取りから取得される場合、揮発性の左オペランドを使用して代入式を評価することの副作用は、式の値が使用されるかどうかによって異なります。完全に恣意的であり、これは奇妙で予期せぬ、文書化されていない動作になります。