将Int转换为两个Shorts返回填充数据/负值

时间:2017-11-23 11:26:22

标签: c# type-conversion int short bitconverter

我有一段简单的代码可以将Int转换为两个short s:

public static short[] IntToTwoShorts(int a)
{
    byte[] bytes = BitConverter.GetBytes(a);
    return new short[] { BitConverter.ToInt16(bytes, 0), BitConverter.ToInt16(bytes, 2) };
}

如果我传入 1851628330 0x6E5D 9B2A ),结果为:

{short[2]}
    [0]: -25814
    [1]: 28253

问题是 -25814 0xFFFF 9B2A

我尝试了各种风格,包括比特移位。发生了什么事?结果不是short,并且没有 16

3 个答案:

答案 0 :(得分:1)

诀窍在于将两个ushort合并到short时使用int

public static short[] IntToTwoShorts(int a) {
  unchecked {
    return new short[] {
       (short) a,
       (short) (a >> 16)
    };
  }
}

public static int FromTwoShorts(short[] value) {
  unchecked {
    if (null == value)
      throw new ArgumentNullException("value");
    else if (value.Length == 1)
      return (ushort)value[0]; // we don't want binary complement here 
    else if (value.Length != 2)
      throw new ArgumentOutOfRangeException("value"); 

    return (int)((value[1] << 16) | (ushort)value[0]); // ... and here
  }
}

意外行为的原因是负数(如-25814)表示为binary complements,因此您拥有相同的值(-25814在不同的整数类型中表示不同的

-25814 ==             0x9b2a // short, Int16
-25814 ==         0xffff9b2a //   int, Int32
-25814 == 0xffffffffffff9b2a //  long, Int64 

一些测试

int a = 1851628330;
short[] parts = IntToTwoShorts(a);

Console.WriteLine($"[{string.Join(", ", parts)}]");
Console.WriteLine($"{FromTwoShorts(parts)}");
Console.WriteLine($"{FromTwoShorts(new short[] { -25814 })}");
Console.WriteLine($"0x{FromTwoShorts(new short[] { -25814 }):X}");

结果:

[-25814, 28253]
1851628330
39722
0x9B2A

答案 1 :(得分:0)

我会用这样的方法解决问题:

public static short[] IntToTwoShorts(int a)
{
    short retVar[2];
    //Upper 16 byte masked with 0x0000FFFF
    retVar[0] = (short) (a >> 16) & (65535);
    //Lower 16 byte masked with 0x0000FFFF
    retVar[1] = (short) (a >> 0) & (65535);

    return retVar;
}

答案 2 :(得分:0)

问题不在于代码(尽管可能有更多efficient ways to do split integers)。通过尝试将int表示为两个带符号的16位短路,您现在需要考虑符号位可能同时出现在shorts中。因此评论ushort[]将是两个16位值表示的更合适的选择。

问题似乎在于理解为什么4字节有符号整数(DWORD)无法在两个2字节有符号短路(WORD)中有效表示。

  

问题是-25814是0xFFFF 9B2A

事实并非如此 - 您已将-25814表示为short,因此它不可能是0xFFFF 9B2A - 这是32位表示。它的16位表示只是9B2A

如果您在Windows上打开计算器,并将模式设置为程序员,并修改HEXDEC基础,然后在DWORD和{{1}之间翻转在表示值时,您应该看到从32位int中提取的16位值被正确表示(假设您理解了表示形式):

您原来的32位整数(DWORD)是1851628330:

Original DWord

高位字28253没有设置符号位,因此您似乎对转换为6E5D感到满意:

enter image description here

但是,如果低位字被解释为带符号短路,那么您会发现它的位符号已设置,因此它报告为负值。但是,表示(位和十六进制)确实正确表示原始32位int的最后16位。

enter image description here