如何BitConverter.ToInt32工作
本文关键字:工作 ToInt32 BitConverter 如何 | 更新日期: 2023-09-27 18:13:07
这是一个方法-
using System;
class Program
{
static void Main(string[] args)
{
//
// Create an array of four bytes.
// ... Then convert it into an integer and unsigned integer.
//
byte[] array = new byte[4];
array[0] = 1; // Lowest
array[1] = 64;
array[2] = 0;
array[3] = 0; // Sign bit
//
// Use BitConverter to convert the bytes to an int and a uint.
// ... The int and uint can have different values if the sign bit differs.
//
int result1 = BitConverter.ToInt32(array, 0); // Start at first index
uint result2 = BitConverter.ToUInt32(array, 0); // First index
Console.WriteLine(result1);
Console.WriteLine(result2);
Console.ReadLine();
}
}
输出1638516385
我只想知道这是怎么发生的?
BitConverter.ToInt32
的文档实际上有一些很好的例子。假设BitConverter.IsLittleEndian
返回true, array[0]
是最低有效字节,如您所示…虽然array[3]
不只是符号位,但它是最重要的字节,包括符号位(作为第7位),但其余的位用于大小。
所以在你的例子中,最低有效位字节是1,下一个字节是64 -所以结果是:
( 1 * (1 << 0) ) + // Bottom 8 bits
(64 * (1 << 8) ) + // Next 8 bits, i.e. multiply by 256
( 0 * (1 << 16)) + // Next 8 bits, i.e. multiply by 65,536
( 0 * (1 << 24)) // Top 7 bits and sign bit, multiply by 16,777,216
等于16385。如果设置了符号位,则需要以不同的方式考虑这两种情况,但在这种情况下很简单。
转换成以256为基数的数字。所以在你的例子中:1+64*256 = 16385
查看。net 4.0框架参考源代码,BitConverter
确实按照Jon的回答工作,尽管它使用指针(unsafe
代码)来处理数组。
然而,如果第二个参数(即startindex
)可以被4整除(如您的示例中的情况),则框架采取快捷方式。它接受指向value[startindex]
的byte
指针,将其强制转换为int
指针,然后对其解引用。无论IsLittleEndian
是否为真,此技巧都有效。
从高层次来看,这基本上只是意味着代码指向byte
数组中的4个字节,并明确声明,"那里的内存块是int
!"(然后返回它的副本)。当您考虑到在底层,int
是只是一块内存时,这是完全合理的。
ToUint32
方法的源代码:
return (uint)ToInt32(value, startIndex);
array[0] = 1;//最低//0x01
array[1] = 64;//0x40
array[2] = 0;//0x00
array[3] = 0;//符号位0 x00
如果合并每个十六进制值0x00004001
MSDN文档解释了
您可以自己查找- https://referencesource.microsoft.com/#mscorlib/system/bitconverter.cs,e8230d40857425ba
如果数据是字对齐的,它只会将内存指针强制转换为int32类型。
return *((int *) pbyte);
否则,它使用字节内存指针值的位逻辑。
对于那些对Little Endien和Big Endien有问题的人。我使用下面的包装器函数来处理它。
public static Int16 ToInt16(byte[] data, int offset)
{
if (BitConverter.IsLittleEndian)
{
return BitConverter.ToInt16(BitConverter.IsLittleEndian ? data.Skip(offset).Take(2).Reverse().ToArray() : data, 0);
}
return BitConverter.ToInt16(data, offset);
}
public static Int32 ToInt32(byte[] data, int offset)
{
if (BitConverter.IsLittleEndian)
{
return BitConverter.ToInt32(BitConverter.IsLittleEndian ? data.Skip(offset).Take(4).Reverse().ToArray() : data, 0);
}
return BitConverter.ToInt32(data, offset);
}
public static Int64 ToInt64(byte[] data, int offset)
{
if (BitConverter.IsLittleEndian)
{
return BitConverter.ToInt64(BitConverter.IsLittleEndian ? data.Skip(offset).Take(8).Reverse().ToArray() : data, 0);
}
return BitConverter.ToInt64(data, offset);
}