BinaryReader.ReadInt64
被设计为小端序。根据文档:
BinaryReader以小端序格式读取此数据类型。
实际上,我们可以使用Reflector检查BinaryReader.ReadInt64
的源代码。
public virtual long ReadInt64() {
this.FillBuffer(8);
uint num = (uint) (((this.m_buffer[0] |
(this.m_buffer[1] << 0x08)) |
(this.m_buffer[2] << 0x10)) |
(this.m_buffer[3] << 0x18));
uint num2 = (uint) (((this.m_buffer[4] |
(this.m_buffer[5] << 0x08)) |
(this.m_buffer[6] << 0x10)) |
(this.m_buffer[7] << 0x18));
return (long) ((num2 << 0x20) | num);
}
展示使用 BinaryReader.ReadInt64
读取的结果是小端字节序,与底层机器体系结构无关。
现在,BitConverter.ToInt64
应该会考虑您底层机器的字节序。在 Reflector 中,我们可以看到:
public static unsafe long ToInt64(byte[] value, int startIndex) {
// argument checking elided
fixed (byte* numRef = &(value[startIndex])) {
if ((startIndex % 8) == 0) {
return *(((long*) numRef));
}
if (IsLittleEndian) {
int num = (numRef[0] << 0x00) |
(numRef[1] << 0x08) |
(numRef[2] << 0x10) |
(numRef[3] << 0x18);
int num2 = (numRef[4] << 0x00) |
(numRef[5] << 0x08) |
(numRef[6] << 0x10) |
(numRef[7] << 0x18);
return (((long) ((ulong) num)) | (num2 << 0x20));
}
int num3 = (numRef[0] << 0x18) |
(numRef[1] << 0x10) |
(numRef[2] << 0x08) |
(numRef[3] << 0x00);
int num4 = (numRef[4] << 0x18) |
(numRef[5] << 0x10) |
(numRef[6] << 0x08) |
(numRef[7] << 0x00);
return (((long) ((ulong) num4)) | (num3 << 0x20));
}
因此,我们在这里看到的是,如果startIndex
模8等于零,则会直接将从地址numRef
开始的8个字节进行强制转换。由于对齐问题,这种情况被特殊处理。代码行
return *(((long *) numRef));
直接翻译成
ldloc.0 ;pushes local 0 on stack, this is numRef
conv.i ;pop top of stack, convert to native int, push onto stack
ldind.i8 ;pop address off stack, indirect load from address as long
ret ;return to caller, return value is top of stack
所以我们可以看到,在这种情况下,关键是
ldind.i8
指令。CLI对底层计算机的字节序是不可知的,它让JIT编译器处理这个问题。在小端机器上,
ldind.i8
将把高地址加载到更高位,而在大端机器上,
ldind.i8
将把高地址加载到较低的字节。因此,在这种情况下,字节序被正确处理了。
在另一种情况下,你可以看到有一个显式检查静态属性
BitConverter.IsLittleEndian
。在小端情况下,缓冲区被解释为小端(因此内存
{0x00、0x01、0x02、0x03、0x04、0x05、0x06、0x07}
被解释为长整型
0x0706050403020100
),而在大端情况下,缓冲区被解释为大端(因此内存
{0x00、0x01、0x02、0x03、0x04、0x05、0x06、0x07}
被解释为长整型
0x0001020304050607
)。因此,对于
BitConverter
,所有的问题都归结为底层计算机的字节序。我注意到你的机器是Windows 7 x64上的Intel芯片,而Intel芯片是小端字节序的。我注意到,在Reflector中,
BitConverter
的静态构造函数定义如下:
static BitConverter() {
IsLittleEndian = true;
}
这是在我的 Windows Vista x64 机器上。 (在 Xbox 360 上的 .NET CF 可能会有所不同。) 没有理由让 Windows 7 x64 与此不同。因此,你确定 BitConverter.IsLittleEndian
是 false
吗?它应该是 true
,因此你看到的行为是正确的。
BitConverter.IsLittleEndian
是 false 吗?Intel 机器都是小端字节序。 - jason