Int32.max上的Bitshift失败了

时间:2014-02-05 21:36:25

标签: c# bit-manipulation

好的,我有两种方法

public static long ReadLong(this byte[] data)
{
    if (data.Length < 8) throw new ArgumentOutOfRangeException("Not enough data");

    long length = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24
            | data[4] << 32 | data[5] << 40 | data[6] << 48 | data[7] << 56;
    return length;
}
public static void WriteLong(this byte[] data, long i)
{
    if (data.Length < 8) throw new ArgumentOutOfRangeException("Not enough data");

    data[0] = (byte)((i >> (8*0)) &  0xFF);
    data[1] = (byte)((i >> (8*1)) &  0xFF);
    data[2] = (byte)((i >> (8*2)) &  0xFF);
    data[3] = (byte)((i >> (8*3)) &  0xFF);
    data[4] = (byte)((i >> (8*4)) &  0xFF);
    data[5] = (byte)((i >> (8*5)) &  0xFF);
    data[6] = (byte)((i >> (8*6)) &  0xFF);
    data[7] = (byte)((i >> (8*7)) &  0xFF);
}

所以WriteLong正常工作(针对BitConverter.GetBytes()验证)。问题是ReadLong。我对这些东西有相当好的理解,但是我猜测正在发生的事情是或者操作是以32位整数发生的,所以在Int32.MaxValue它会翻身。我不确定如何避免这种情况。我的第一直觉是从下半部分制作一个int,从上半部分制作一个int并将它们组合起来,但是我知道甚至不知道从哪里开始,所以这就是我试过的...... / p>

public static long ReadLong(byte[] data)
{
    if (data.Length < 8) throw new ArgumentOutOfRangeException("Not enough data");

    long l1 = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24;
    long l2 = data[4] | data[5] << 8 | data[6] << 16 | data[7] << 24;
    return l1 | l2 << 32;
}

这不起作用,至少对于较大的数字不起作用,它似乎适用于零以下的所有内容。

以下是我如何运行它

void Main()
{
    var larr = new long[5]{
        long.MinValue,
        0,
        long.MaxValue,
        1,
        -2000000000
    };
    foreach(var l in larr)
    {
        var arr = new byte[8];
        WriteLong(ref arr,l);
        Console.WriteLine(ByteString(arr));
        var end = ReadLong(arr);
        var end2 = BitConverter.ToInt64(arr,0);
        Console.WriteLine(l + " == " + end + " == " + end2);
    }
}

这是我得到的(使用修改后的ReadLong方法)

0:0:0:0:0:0:0:128
-9223372036854775808 == -9223372036854775808 == -9223372036854775808
0:0:0:0:0:0:0:0
0 == 0 == 0
255:255:255:255:255:255:255:127
9223372036854775807 == -1 == 9223372036854775807
1:0:0:0:0:0:0:0
1 == 1 == 1
0:108:202:136:255:255:255:255
-2000000000 == -2000000000 == -2000000000

2 个答案:

答案 0 :(得分:3)

问题不在于,或者是bithift。这必须做多久。目前,数据[i]被隐含地转换为int。只需将其改为长即可。即。

 public static long ReadLong(byte[] data)
 {
     if (data.Length < 8) throw new ArgumentOutOfRangeException("Not enough data");

     long length = (long)data[0] | (long)data[1] << 8 | (long)data[2] << 16 | (long)data[3] << 24
                | (long)data[4] << 32 | (long)data[5] << 40 | (long)data[6] << 48 | (long)data[7] << 56;
     return length;
 }

答案 1 :(得分:0)

您正在进行int算术,然后分配给long,请尝试:

long length = data[0] | data[1] << 8L | data[2] << 16L | data[3] << 24L
        | data[4] << 32L | data[5] << 40L | data[6] << 48L | data[7] << 56L;

这应该将你的常量定义为强制它使用长算术的长度。

编辑:根据下面的评论,这可能不起作用,因为bitshift在左侧需要许多运算符,它只在右侧使用int。格奥尔格应该是公认的答案。