11 August 2009 0 Comments

MSDN Flash 2009/8/11 No.330 の答え – (1)

今回の MSDN Flashでは 2つのコードを掲載しました。今回は 1つ目のコードの問題について解説したいと思います。 掲載したコードは以下の通りです。 int i1 = -2; unsigned int i2 = 1; char *s = “Hello”; printf(“%s”, s + 1 + (i1 + i2)); 期待される実行結果は 32bit環境では ”Hello” と表示、64bit環境では不定…大抵はアクセス違反例外によるプログラムの異常終了となります。 直接値を代入して 4行目を展開すると、 s + 1 + (i1 + i2) = s + 1 + (-2 + 1) = s + 1 – 1 = s となりそうなものですが、なぜそうならないのでしょうか?その答えは Usual Arithmetic Conversions にあります。 整数同士の演算において片方が int でもう片方が unsigned int の場合は int は unsigned int に変換され、結果は unsigned int となります。 今回のコードでは int i1 = -2, unsigned int i2 = 1 であるので i1 + i2 は (unsigned int)i1 + i2 = (unsigned int)-2 + 1 = 0xFFFFFFFE + 1 = 0xFFFFFFFF となります。よって演算結果は s + 1 + (i1 + i2) = s + 1 + (0xFFFFFFFE + 1) = s + 1 + 0xFFFFFFFF = s + 0×100000000 となります。 32bit環境では 0×100000000 の 2 32 の剰余が 0 となるため問題は発覚せず期待された動作となります。これを整数のラップアラウンドと呼びます。一方、64bit環境では s + 0×100000000 が printf関数に渡されるためアクセス違反例外が発生します。 そもそも整数やポインタの演算における意図しないラップアラウンドは避けるべきですが、今回のように隠れていた問題が 64bit環境へ移行時に発覚することがあります。 MSDN Flash ニュースレター最新号および購読は こちら から

More: 
MSDN Flash 2009/8/11 No.330 の答え – (1)

If you liked this post, buy me a Coffee.

Leave a Reply