VB.NET代码返回的结果与C#代码不同

时间:2012-04-20 07:57:30

标签: c# vb.net bit-manipulation runtime-error

C#中的以下代码给出结果“228452386”

UInt32 a;

int k = 0;

a = 0x9E3779B9;

a += (UInt32)(url[k + 0] + (url[k + 1] << 8) + (url[k + 2] << 16) + (url[k + 3] << 24));

运行上面的代码后,“a”包含“228452386”。

VB.NET中的以下相同代码导致“算术运算导致溢出”。基本上最后一个语句返回值“1868983913”,因此生成运行时错误。

Dim a As UInt32

Dim k As Integer = 0

a = &H9E3779B9UI

a += CUInt(AscW(url(k + 0)) + (AscW(url(k + 1)) << 8) + (AscW(url(k + 2)) << 16) + (AscW(url(k + 3)) << 24))

请注意上面代码中的变量“url”可以是任何字符串,两个代码都是相同的。

当我在C#和VB.NET中运行以下语句时,它们都返回相同的值

C#

(UInt32)(url[k + 0] + (url[k + 1] << 8) + (url[k + 2] << 16) + (url[k + 3] << 24))

VB.NET

CUInt(AscW(url(k + 0)) + (AscW(url(k + 1)) << 8) + (AscW(url(k + 2)) << 16) + (AscW(url(k + 3)) << 24))

两个语句都为“url”“info:microsoft.com”返回值“1868983913”。但是当我使用 a + = ......... 运行完整语句时,VB.NET会出错,而C#返回值“228452386”。

3 个答案:

答案 0 :(得分:2)

你有一个溢出,因为添加你添加的两个数字的结果大于UInt中的数字。

结果数字是33位数,UInts只适合32位。

  • 在C#中,最重要的位被切断,保持适合UInt的32位。 (这个新值不是添加数字的实际结果。)
  • 在VB.NET中,您会收到一个异常,说明该号码不合适。

VB.NET编译器(或VS)允许您打开此溢出检查,以便在这种情况下VB.NET的行为类似于C#。

答案 1 :(得分:1)

VB.NET会自动插入溢出测试,而C#则不会。等效的C#代码是:

UInt32 a;
int k = 0;
a = 0x9E3779B9;
checked{
    a += (UInt32)(url[k + 0] + (url[k + 1] << 8) + (url[k + 2] << 16) + (url[k + 3] << 24));
}

编辑:更改了代码示例以符合已修改的问题。

答案 2 :(得分:0)

使用以下VB.NET代码:

    a += CUInt(AscW(url(k + 0))) + CUInt((AscW(url(k + 1)) << 8)) + CUInt((AscW(url(k + 2)) << 16)) + CUInt((AscW(url(k + 3)) << 24))

AscW返回一个整数(已签名),你需要的是无符号。

修改

这有效:

    Dim a As Int64
    Dim result As UInt32

    Dim k As Integer = 0

    Dim url As String = "info:microsoft.com"

    a = &H9E3779B9UI

    Dim a1 As UInt32 = 0
    Dim a2 As UInt32 = 0
    Dim a3 As UInt32 = 0
    Dim a4 As UInt32 = 0

    a1 = AscW(url(k + 0))
    a2 = AscW(url(k + 1)) << 8
    a3 = AscW(url(k + 2)) << 16
    a4 = AscW(url(k + 3)) << 24

    a = (a + a1 + a2 + a3 + a4) And &HFFFFFFF
    result = Convert.ToUInt32(a)