DOBON.NET DOBON.NETプログラミング掲示板過去ログ

[VB.NET] VB2005でUInt32の型に&hFFFFFFFF

環境/言語:[XP/VB.NET2005 Express/CPU32bit]
分類:[.NET]

こんにちは、どらごらです。

VB2005のExpressを使ってます。

バグっぽいのを見つけたのですが、どの部分の仕様(?)バグ?なのか確認したいので、
VB.NET2003やVS2005のC#でも発生するのか、確認していただけないでしょうか?
Frameworkの仕様なのか、VB.NETの言語仕様なのかはっきりさせたいためです。


内容は以下のとおりです。

[代入エラーが発生するパターン]
Dim hoge1 As UInt32 = &HFFFFFFFF
 →定数式は、型'UInteger'では表現できません。
 ※4バイトはOKのハズ
Dim hoge2 As UInteger = &HFFFFFFFF
 →hoge1と一緒
Dim hoge3 As UInt64 = &HFFFFFFFFFFFFFFFF
 →定数式は、型'ULong'では表現できません。
 ※8バイトはOKのハズ
Dim hoge4 As UInt64 = 18446744073709551615
 →オーバーフローしました
 ※0xFFFFFFFFFFFFFFFF(8Byte) = 18446744073709551615
Dim hoge10 As UInt16 = -1
Dim hoge11 As UInt32 = -1
Dim hoge12 As UInt64 = -1
 →定数式は、型'Uxxx'では表現できません。

[代入が成功するパターン]
Dim hoge5 As UInt16 = &HFFFF
Dim hoge6 As UInt32 = &H7FFFFFFF
Dim hoge7 As UInteger = &H7FFFFFFF
Dim hoge8 As UInt32 = 4294967295
Dim hoge9 As UInt64 = &H7FFFFFFFFFFFFFFF

[バグだと思う理由]
・UInt16型には符号ビット(16bit)を含めた、代入ができる
・UInt32型に10進(294967295)が代入できるのに、符号ビット含めた16進(0xFFFFFFFF)だと代入できない
・UInt64型には10進(18446744073709551615)も、符号ビット含めた16進(0xFFFFFFFFFFFFFFFF)も代入できない
・UInt64型にはMAX値を入れる方法がない

P.S.
64ビットCPUなら可能なのかな?
2006/03/29(Wed) 00:05:47 編集(投稿者)

> Dim hoge1 As UInt32 = &HFFFFFFFF
>  →定数式は、型'UInteger'では表現できません。
>  ※4バイトはOKのハズ
サイズが一致していれば良いと言うものではありませんよね。

&HFEDCBA09I と
&HFEDCBA09UI は、別の値ですから。


> Dim hoge3 As UInt64 = &HFFFFFFFFFFFFFFFF
これも同じ事。下記の結果を比較してみましょう。

Dim S1 As String = &HFFFFFFFFFFFFFFFF.GetType().Name
Dim S2 As String = &HFFFFFFFFFFFFFFFFUL.GetType().Name


> Dim hoge4 As UInt64 = 18446744073709551615
>  →オーバーフローしました
>  ※0xFFFFFFFFFFFFFFFF(8Byte) = 18446744073709551615
小数部のないリテラル数値は、IntegerまたはLong型として解釈される事に
なっています。(バグというわけではなく、そういう言語仕様なのです)
この場合は、
 Dim hoge4 As UInt64 = 18446744073709551615UL
のように、UInteger型 や ULong 型のリテラルを使ってください。


> UInt64型にはMAX値を入れる方法がない
指定さえ間違っていなければ、問題なく入れられますよ。

http://msdn2.microsoft.com/ja-jp/library/s9cz43ek(VS.80).aspx
などに書かれている、リテラルの型宣言文字を使いましょう。

もしそれが使えなくても、『MAX値を入れる方法』といえば、普通は
UInt64.MaxValue を使うでしょうし、それすらなかったとしても、
Convert.ToUInt64 などを使う事ができるかと。


> ・UInt16型には符号ビット(16bit)を含めた、代入ができる
Unsinged ゆえ、そもそも符号ビットが存在しませんから、
符号ビットを含むというのは語弊があるかも知れません。

で、先にも書きましたが、型指定の無い整数リテラルは、「Integer(Int32)」として
解釈され、それでは足りない場合、「Long(Int64)」として処理される事になります。

ですから、先の例で言うところの
 Dim hoge5 As UInt16 = &HFFFF
というコードについては、右辺が Short(Int16) や UShort(UInt16) では無く、
Integer(Int32)として認識されていたという事です。
つまり、Integer 型の 65535 なので、UShort に格納できていたわけですね。


> VB.NET2003やVS2005のC#でも発生するのか、確認していただけないでしょうか?
まず、VB.NET 2003 ですが、これは確認できません。

2002/2003 には UShort / UInteger / ULong という型がありませんので、
今回のコードを使って比較する事ができないからです。

もちろん、VB.NET 2003 で System.UInt32 などを使う事はできますが、それらは
数値としてではなく、単なる構造体という扱いになってしまいますね。


一方、C# については、基本的には VB2005 に近い状況と言えそうです。

C# は、初期のバージョンから、符号無し/符号付き整数の両方をサポートして
いますし、整数リテラルについても、VB2005 と同じように、型を表すサフィックスを
サポートしています。たとえば、「uint myUint = 123U;」などと。

ただし、VB と異なる点もあります。たとえば、C# においては、
  short i = -1;
  ushort u = (ushort)i;
のようなコードを書いた場合、u は 65535 となりますが、
  Dim I As Short = -1
  Dim U As UShort = CUShort(I)
という VB のコードは、オーバーフローとなります。そのため、符号無し型に、
符号無し型のリテラルを代入した場合の動作は、VB2005 の場合と同じですが、
符号付き型のリテラルを代入した場合の動作は、VB2005 の場合と異なります。
レスありがとうございます。

■No15084に返信(魔界の仮面弁士さんの記事)
> 2006/03/29(Wed) 00:05:47 編集(投稿者)
>
>>Dim hoge1 As UInt32 = &HFFFFFFFF
>> →定数式は、型'UInteger'では表現できません。
>> ※4バイトはOKのハズ
> サイズが一致していれば良いと言うものではありませんよね。
>
> &HFEDCBA09I と
> &HFEDCBA09UI は、別の値ですから。

 別の値というのは、認識しています。

 どうもリテラルって言うと、Dim Str$ = "hgoehoge"等の
 型文字というイメージが高くて、強制リテラルの存在を忘れてました。

> もしそれが使えなくても、『MAX値を入れる方法』といえば、普通は
> UInt64.MaxValue を使うでしょうし、それすらなかったとしても、
> Convert.ToUInt64 などを使う事ができるかと。

 MaxValueですか・・・こっちも調査不足でした。

>>・UInt16型には符号ビット(16bit)を含めた、代入ができる
> Unsinged ゆえ、そもそも符号ビットが存在しませんから、
> 符号ビットを含むというのは語弊があるかも知れません。

 確かにそうですね。ここで書きたかったのは正確には
 UInt16型には符号ビット(16bit) → UInt16型にはInt16の符号として使われるビット(16bit目)
 かな?

> ただし、VB と異なる点もあります。たとえば、C# においては、

 なるほど。全体的に基礎部分をまったく忘れてましたね。
 元々やりたかったのは、UInt32の最大値で初期したかったので、
 UInt32.MaxValue > 16進 > 10進
 ↑これで初期値を設定したいと思います。

 勉強になりました。ありがとうございます。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板