paiza記事へのコメントメモ(2016年)


限定投稿整理中に去年(2016年)暮れに話題になったpaiza記事「ツイッターで出題した未定義問題のお詫びと調査と解説について」へ投稿したコメントが出てきたため、マサカリ Advent Calendar 2017に供して供養とさせて頂きます。

当時は該当ブログのコメント欄に投稿したのですが、おそらく非公開設定のためサイトでは表示されていません。なお、記事本文には本コメント指摘を反映頂いたようです。

 . +  .:. . .
+   :.  .  +.
 .  : .  + . .
. :.     .
 .  +  Π
      ||
     (二X二O
       || .+ .
   ∧ ∧ ||
   /⌒ヽ)_||_
_~(  );;;;::\
" "" """""""" ""/;
 ""   """ ""/:;

C/C++言語いずれでも未定義動作になるという結論は正しいのですが、その導出過程(および一部の説明)が適切でないと思います。

それぞれ、C++1z(N4618) §1.9 Paragraph 18: “If a side effect on a memory location (1.7) is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent (1.10), the behavior is undefined.”、C11(N1570) §6.5 Paragraph2: ”If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.” が直接的に未定義動作としている箇所です。

C/C++ともに、2項+演算子オペランドの評価順序は未規定(unspecified)であり、その両オペランドに同一変数に対するインクリメント演算子(i++と++i)を置いているため、それぞれの値の評価(value computation)と副作用(side effect)が順序付けされず(unsequenced)、その結果として未定義の動作(behavior is undefined)になります。

本文「i++の後ろに、+で数値をつないだ場合、動作が定義されてない」「i++ +1は定義されるようになったけど、i++ + iは未定義とあります」はいずれも解釈を誤っており、C++仕様ではiへの代入までを含めて「i = i++ +1は定義されるがi = i++ + iは未定義」と言っています。式(i++ + 数値)のみに着目した場合は、何の問題も生じません。

本文「C++17ではside effectのある式の評価が見直され」も正確ではなく、C++17では一部の演算子でのみ評価順が明示的に規定されます。そこではside effect有無は直接関係しません。