2

重複の可能性:
これらの未定義の動作(i = i ++ + ++ i、i = i ++など)を誰かが説明でき
ますか?次のマクロがアプリケーションにどのような問題をもたらす可能性がありますか?

iOS(Objective Cコード)に実装するためのマクロ拡張を使用したサンプルアプリケーションを作成しました。

それは次のようなものです:

#define SQUARE(x) ( x * x )
main( )
{
   int i = 3, j, k ;
   j = SQUARE( i++ ) ;
   k = SQUARE( ++i ) ;
   printf ( "\nValue of i++ = %d\nValue of ++i = %d", j, k ) ;
}

出力は次のとおりです。

Value of i++ = 9
Value of ++i = 49

期待される出力は次のとおりです。

 Value of i++ = 9
 Value of ++i = 25

この結果に驚いています。私はこのマクロ展開と少し混乱しています。

なぜそれが起こったのですか?理由を見つけるのを手伝ってください。

4

3 に答える 3

6

介在するシーケンス ポイントなしで を複数回変更することにより、未定義の動作を呼び出して います。i

マルコ置換の後、2 つの行は次のようになります。

   j = ( i++ * i++ ) ;
   k = ( ++i * ++i ) ;
于 2013-01-21T09:37:57.937 に答える
6

これは、シーケンスポイントなしで同じステートメントで同じ変数を2回増加させるため、実際には未定義の動作です(別のコンパイラまたは同じコンパイラの次の実行に依存するべきではありません)が、これはこれで起こるようです場合;

#define SQUARE(x) ( x * x )
j = SQUARE( i++ ) ;
k = SQUARE( ++i ) ;

に拡大します

j = (i++ * i++);     // Compiler could do i * i, then increment twice, or use i * (i + 1), or...  

k = (++i * ++i);     // Same as above

これは未定義の動作であるため、コンパイラは自由にやりたいことを実行できます (古いバージョンの gcc ではプログラムが nethack を起動していました ;-)。より正確に言えば、コンパイラは、未定義の動作が呼び出されることはないと想定することができ、コードが「通常の」ケースで正しく機能することを確認します。予期しない場合に何が起こるかは、誰の賭けでもあります。

于 2013-01-21T09:38:24.687 に答える
1

これは、2 つのシーケンス ポイント間で 1 つの変数を 2 回インクリメントしているためです。したがって、これは未定義の動作です

   int i = 3, j, k ;
   j = SQUARE( i++ ) ; // it becomes (i++ * i++)
   k = SQUARE( ++i ) ; // it becomes (++i * ++i)

したがって、来る出力は未定義です。

あなたが得ている出力は、最初の式の後に i が 2 回インクリメントされるためです。そのため、前のインクリメントのために i が 2 回インクリメントされる 2 番目の式では、ポストのインクリメントの上でも 2 回インクリメントされます。

j=(i++ * i++)//it comes 3*3 

k=(++i * ++i)// it comes 7 as two increments of above xpression
于 2013-01-21T09:41:59.760 に答える