1. ホーム
  2. c

[解決済み】なぜこれらのコンストラクトはプリインクリメントとポストインクリメントを使用して未定義の動作をしているのでしょうか?

2022-03-23 14:25:48

質問

#include <stdio.h>

int main(void)
{
   int i = 0;
   i = i++ + ++i;
   printf("%d\n", i); // 3

   i = 1;
   i = (i++);
   printf("%d\n", i); // 2 Should be 1, no ?

   volatile int u = 0;
   u = u++ + ++u;
   printf("%d\n", u); // 1

   u = 1;
   u = (u++);
   printf("%d\n", u); // 2 Should also be one, no ?

   register int v = 0;
   v = v++ + ++v;
   printf("%d\n", v); // 3 (Should be the same as u ?)

   int w = 0;
   printf("%d %d\n", ++w, w); // shouldn't this print 1 1

   int x[2] = { 5, 8 }, y = 0;
   x[y] = y ++;
   printf("%d %d\n", x[0], x[1]); // shouldn't this print 0 8? or 5 0?
}

解決方法は?

C言語には未定義動作という概念があります。つまり、ある言語構成は構文的には有効ですが、コードを実行したときの動作を予測することはできません。

私の知る限り、この規格では明示的に なぜ 未定義の動作という概念は存在します。私の考えでは、言語設計者がセマンティクスに余裕を持たせたかっただけで、すべての実装がまったく同じ方法で整数のオーバーフローを処理することを要求するのではなく、その代わりに、もし整数のオーバーフローを引き起こすコードを書けば何でも起こりうるように、動作を未定義にしたのだと思います。

では、それを踏まえた上で、なぜこれらの"issue"なのでしょうか?この言語では、あることが原因で 未定義の動作 . 問題はなく、"should" は関係ありません。もし、関係する変数の1つが宣言されたときに、未定義の動作が変化するなら、それは volatile しかし、それは何の証明にも変化にもなりません。それは 未定義 その挙動を推論することはできません。

あなたの最も面白そうな例、それは

u = (u++);

は、未定義の動作の教科書的な例です (Wikipedia の シーケンスポイント ).