2004年11月17日
川俣晶の縁側ソフトウェア技術雑記total 11707 count

C#において、なぜIntPtr ptr = new IntPtr (0x80000000);がオーバーフロー例外になるのか

Written By: 川俣 晶連絡先

 実に私好みの面白い話題なので、勝手に取り上げさせて頂きました。

 [技術情報][.NET] IntPtr の値域?で渋木さんが嘆いているので、ちょっと調べてみました。

 C#において、なぜIntPtr ptr = new IntPtr (0x80000000);がオーバーフロー例外になるのかです。

現象の確認 §

 まず、こんなコードを走らせてみます。

using System;

namespace ConsoleApplication41

{

    class Class1

    {

        [STAThread]

        static void Main(string[] args)

        {

            IntPtr ptr = new IntPtr (0x80000000);

        }

    }

}

 確かに例外を投げてしまいます。

そもそも0x80000000ってintに代入できるのか? §

 そもそも0x80000000ってintに代入できるのだろうか、という当然の疑問が発生します。

 というわけで、こんなコードを書いてみました。

using System;

namespace ConsoleApplication41

{

    class Class1

    {

        [STAThread]

        static void Main(string[] args)

        {

            int a = 0x80000000;

        }

    }

}

 これは一発でコンパイルエラーになりました。

d:\w\test\ConsoleApplication41\Class1.cs(10): 型 'uint' を型 'int' に暗黙的に変換できません。

 というわけで、0x80000000はuint型の値で、正の数であることが推測されます。int型では、この正の値を表現することができません。ゆえに、変換はできないのが当然の結末です。

では、なぜ先の例ではコンパイルエラーにならないのか? §

 では、なぜ先の例ではコンパイルエラーにならないのでしょうか?

 それは、IntPtrのコンストラクタにはint64を引数に取るものがあり、それが使われているためだと分かりました。

 64bit符合付き整数であれば、0x80000000 (2147483648)という正の数を扱えます。

 しかし、これは32bit符合付き整数では扱えません。つまり、IntPtrで扱う32bitシステムのポインターは-2147483648~2147483647の範囲の値であることが期待されているにもかかわらず、0x80000000 (2147483648)という値を使おうとしても範囲外であるため、例外が起こるわけですね。

ベテランプログラマの落とし穴か? (2004年11月17日13時45分頃訂正) §

 (この部分は、不適切なサンプル ソースだったので2004年11月17日13時45分頃訂正しました)。

 このような挙動は、CやC++に慣れ親しんだプログラマにとって落とし穴になりがちな問題かもしれません。

 たとえば、Visual Studio.NETでC++のWin32コンソールアプリケーションとして、ちょいちょいと書いて実行すると……。

int _tmain(int argc, _TCHAR* argv[])

{

    unsigned int a = 2147483648;

    signed int b = -2147483648;

    printf("%d",a == b );

    return 0;

}

 変数aの値は正数。変数bの値は負数であるはずなのに、1(一致)という結果が示されます。

 このような符合のルーズさを、C#は継承していないということですね。

 C#で似たようなコードを書いてみます。

using System;

namespace ConsoleApplication41

{

    class Class1

    {

        [STAThread]

        static void Main(string[] args)

        {

            uint a = 2147483648;

            int b = -2147483648;

            Console.WriteLine( a == b );

        }

    }

}

 この結果はFalse(不一致)となります。

Facebook

トラックバック一覧

2004年11月17日re: [技術情報][.NET] IntPtr の値域?From: HIDORI on The Web: 渋木宏明(ひどり) blog

re: [技術情報][.NET] IntPtr の値域? 続きを読む

2004年11月17日re: [技術情報][.NET] IntPtr の値域?From: HIDORI on The Web: 渋木宏明(ひどり) blog

re: [技術情報][.NET] IntPtr の値域? 続きを読む

キーワード【 川俣晶の縁側ソフトウェア技術雑記
【技術雑記】の次のコンテンツ
2004年
12月
01日
日本ウインドウズサーバユーザ会(Japan WiNdows Server Users Group: JWNSUG)
3days 0 count
total 9957 count
【技術雑記】の前のコンテンツ
2004年
11月
16日
ソフト冒険記・Groovy
3days 0 count
total 3281 count

このコンテンツを書いた川俣 晶へメッセージを送る

[メッセージ送信フォームを利用する]

メッセージ送信フォームを利用することで、川俣 晶に対してメッセージを送ることができます。

この機能は、100%確実に川俣 晶へメッセージを伝達するものではなく、また、確実に川俣 晶よりの返事を得られるものではないことにご注意ください。

このコンテンツへトラックバックするためのURL

https://mag.autumn.org/tb.aspx/20041117123623
サイトの表紙【技術雑記】の表紙【技術雑記】のコンテンツ全リスト 【技術雑記】の入手全リスト 【技術雑記】のRSS1.0形式の情報このサイトの全キーワードリスト 印刷用ページ

管理者: 川俣 晶連絡先

Powered by MagSite2 Version 0.36 (Alpha-Test) Copyright (c) 2004-2021 Pie Dey.Co.,Ltd.