C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: C#とVB.NETのByte型定義について


(過去ログ 109 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■64828 / inTopicNo.1)  C#とVB.NETのByte型定義について
  
□投稿者/ Ante (14回)-(2013/01/15(Tue) 09:54:53)

分類:[VB.NET/VB2005 以降] 

お世話になります。
C#とVB.NETのByte型の挙動について(Byte型だけではないとは思いますが)お伺いしたいことがあります。

例えば、以下のような構文を書いたときに、C#では255を超えた場合、自動で0へ初期化されますが、
VB.NETではオーバーフローエラーとなります。

◆C#
private void button1_Click(object sender, EventArgs e)
{
    Byte _controlNum = 0;

    for (int i = 0; i <= 300; i++)
    {
        _controlNum += 1;
    }
}

◆VB.NET
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim _controlNum As [Byte] = 0

    For i As Integer = 0 To 300
        _controlNum += 1
    Next

End Sub

つまりは、VB.NETではByte型にて宣言したとしても、上記コードの場合、
If _controlNum = 255 Then
    _controlNum = 0
End If

のように、255の場合は0とするようなコードが必要となるのでしょうか?
現在は上記にてエラーを回避していますが、何か理由がみえず、気持ち悪く思っています。

言語仕様ということであればそれまでですが、皆様の見解をお聞かせください。

よろしくお願いいたします。

引用返信 編集キー/
■64829 / inTopicNo.2)  Re[1]: C#とVB.NETのByte型定義について
□投稿者/ 774RR (45回)-(2013/01/15(Tue) 11:01:48)
Byte という型は [0, 255] まで値を保持でき 256 は保持できないという仕様。
255+1 演算の結果として、本来なら正しい結果として 256 という値が得られるはずだが、
それは Byte に入らないため、オーバーフローしてしまっている。
・C# のデフォルトでは、チェックしない(代わりに正しくない 0 という値が得られる)
・VB のデフォルトでは、チェックする(結果としてプログラムが停止している)
となっているだけのこと。

255+1 という式の結果は 256 であるべきか 0 であるべきか?
誤った結果で処理を継続した結果として、以後まったく正しくない処理になる可能性があるが、是か非か?
のデフォルト選択肢が C# と VB で違うわけだ。

どうすべきかは、どうしたいのか?次第かと。

VB で「オーバーフローチェックをしたくない」のであれば、あまりいい手段が無くて
http://www.atmarkit.co.jp/fdotnet/vb6tonet/vb6tonet26/vb6tonet26_01.html#overflow
とか。俺としてはあまりお勧めできないかな。

逆に C# ではオーバーフローチェックをプログラム内部で自己制御できるっぽい。
checked, unchecked キーワードで調べてみるといい。

引用返信 編集キー/
■64830 / inTopicNo.3)  Re[1]: C#とVB.NETのByte型定義について
□投稿者/ 魔界の仮面弁士 (116回)-(2013/01/15(Tue) 11:13:22)
2013/01/15(Tue) 11:23:01 編集(投稿者)

No64828 (Ante さん) に返信
> 言語仕様ということであればそれまでですが、皆様の見解をお聞かせください。

言語仕様というよりは、コンパイルオプションの動作によるものです。
オプションの初期値が on か off かの違いですね。


> C#では255を超えた場合、自動で0へ初期化されますが、

C# では、checked モードだとオーバーフローとなり、
unchecked モードでは 0 に戻ることになります。

 for (int i = 0; i <= 300; i++)
 {
  //checked { _controlNum += 1; }
  unchecked { _controlNum += 1; }
 }


コードで checked / unchecked の指定を行わなかった場合は、
コンパイラオプション /checked の設定に従います。

Visual Studio では、プロジェクトプロパティの[ビルドオプション]タブの
[詳細設定]ボタンから、「演算のオーバーフローおよびアンダーフローのチェック」
のチェックボックスにて変更できます。



> VB.NETではオーバーフローエラーとなります。

VB.NET には、C# でいうところの checked / unchecked に相当する構文は
用意されていませんが、コンパイラオプション /removeintchecks にて、
このオーバーフロー判定をスキップできます。
既定値は Off(オーバーフローさせる)なので、エラーになるわけですね。
これを Visual Studio で設定する場合には、プロジェクトプロパティの
[コンパイル]タブから[詳細コンパイル オプション]ボタンにて
「整数オーバーフローのチェックを解除」を修正してください。


ちなみに VB6 も同様であり、プロジェクト プロパティの[コンパイル]タブから
[最適化の詳細設定]-[整数の桁あふれチェックを削除] で変更できます。


ついでに IL レベルで言えば、桁あふれをチェックしない時には
0x58 の「add」が用いられ、桁あふれをチェックする場合には
0xD6 の「add.ovf」が用いられることになります。(VB/C# いずれも同様)

同様に、Byte 型への格納時においても、
0xD2「conv.u1」で変換するのか、それとも
0xB4 「conv.ovf.u1」を用いるかの違いが生じます。
引用返信 編集キー/
■64832 / inTopicNo.4)  Re[2]: C#とVB.NETのByte型定義について
□投稿者/ Ante (15回)-(2013/01/15(Tue) 11:30:30)
774RR様
ご回答ありがとうございます。

今回の場合、C#で動作しているプログラムをVB.NETに置き換える作業を行っています。
そこで、上述の挙動の違いが発覚しました。

>255+1 という式の結果は 256 であるべきか 0 であるべきか?
これは当該プログラムが255+1は0となっているため、0であるべきです。
そのため、

If _controlNum = 255 Then
_controlNum = 0
End If

を動作させた次第でございます。

魔界の仮面弁士様

いつもお世話になります。

>言語仕様では無く、コンパイルオプションの動作によるものです。
>オプションの初期値が on か off かの違いですね。

コンパイルオプション自体触れたことがありませんでした。
今回を機に少し学習したいと思います。

>VB.NET には、C# でいうところの checked / unchecked に相当する構文は
>用意されていませんが、コンパイラオプション /removeintchecks にて、
>このオーバーフロー判定をスキップできます(既定値は Off です)。
>Visual Studio では、プロジェクトプロパティの[コンパイル]タブから
>[詳細コンパイル オプション]ボタンから「整数オーバーフローのチェックを解除」です。

上記の「整数オーバーフローのチェックを解除」を行うことで、
他のソースコードにも影響を及ぼしかねないので、やはり、

If _controlNum = 255 Then
_controlNum = 0
End If

のコードでしのごうと思っています。

何度かご回答いただいており、大変勉強させていただいています。

ありがとうございました。
解決済み
引用返信 編集キー/
■64833 / inTopicNo.5)  Re[3]: C#とVB.NETのByte型定義について
□投稿者/ 774RR (47回)-(2013/01/15(Tue) 11:59:56)
そのやり方だと +1 が +2 になったら破綻するのであって、もちょっと工夫したほうがいい。
C や C++ のキャストと違って CByte による型明示は縮小変換をしないので

controlnum = CByte((controlnum+1) And 255)
とかのほうが適切なような気がする(本当にコレが適切なのかは案件次第)

解決済み
引用返信 編集キー/
■64834 / inTopicNo.6)  Re[4]: C#とVB.NETのByte型定義について
□投稿者/ shu (138回)-(2013/01/15(Tue) 12:36:23)
その加算部分を関数にでもしてしまった方が複数個所に
同じ対応がしやすいと思います。
引用返信 編集キー/
■64838 / inTopicNo.7)  Re[5]: C#とVB.NETのByte型定義について
□投稿者/ Ante (16回)-(2013/01/15(Tue) 15:40:02)
774RR様、shu様

ご回答ありがとうございます。
仰る通り、破綻してました、、、当該プログラムを切り出し、ロジックの追加を行わず、
C#と同様のコードで動作させるよう、

>Visual Studio では、プロジェクトプロパティの[コンパイル]タブから
>[詳細コンパイル オプション]ボタンから「整数オーバーフローのチェックを解除」です。

上記の「整数オーバーフローのチェックを解除」を行うことで対応します。
コンパイルオプションの問題であれば、これで回避が可能なはずですが、
C#のプログラムと、上述の対応を入れたプログラムとで検証を行うつもりです。

いろいろと勉強させていただいてます。
引用返信 編集キー/
■64840 / inTopicNo.8)  Re[6]: C#とVB.NETのByte型定義について
□投稿者/ 774RR (48回)-(2013/01/15(Tue) 19:20:34)
C# → VB なんてのはわざわざ人力かけなくても自動変換ツールで変換できちゃいそうだし
なんか微妙に無駄な努力というか、なんというか・・・
(google 様も多種多様な変換ツールを教えてくれたので)

とりあえず「デフォルト動作」が違うだけなので、コンパイルオプションの変更だけで
問題なくいけるであろうと思う(どのみち変換後の動作検証は必要だ)
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -