BinaryReader.ReadInt64
設計上、リトルエンディアンです。ドキュメントから:
BinaryReaderは、このデータ型をリトルエンディアン形式で読み取ります。
BinaryReader.ReadInt64
実際、 Reflectorを使用するためのソースを検査できます。
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
、基盤となるマシンのエンディアンを尊重するとします。リフレクターで見ることができます
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を法とするゼロと合同である場合、アドレスで始まる8バイトから直接キャストが実行されるということnumRef
です。このケースは、アライメントの問題のために特別に処理されます。コードの行
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
それはすべて、アンダーイリングマシンのエンディアンに帰着します。Windows7x64のIntelチップを使用していることに注意してください。Intelチップはリトルエンディアンです。BitConverter
Reflectorでは、の静的コンストラクターは次のように定義されていることに注意してください。
static BitConverter() {
IsLittleEndian = true;
}
これは私のWindowsVistax64マシンにあります。(たとえば、XBox360の.NETCFでは異なる場合があります。)Windows7x64が異なる理由はありません。したがって、それは確かBitConverter.IsLittleEndian
ですfalse
か?それはそうあるべきでtrue
あり、したがってあなたが見ている振る舞いは正しいです。