C# はエンディアンに敏感ですか? たとえば、次のようなコードになります。
int a = 1234567;
short b = *(short*)&i;
常に同じ値を b に割り当てます。もしそうなら、それはどのような値になりますか?
そうでない場合、ポインターを含むコードの場合、エンディアンに対処するための良い方法は何ですか?
C# はエンディアンに敏感ですか? たとえば、次のようなコードになります。
int a = 1234567;
short b = *(short*)&i;
常に同じ値を b に割り当てます。もしそうなら、それはどのような値になりますか?
そうでない場合、ポインターを含むコードの場合、エンディアンに対処するための良い方法は何ですか?
C# はエンディアンを定義しません。実際には、おそらく常にリトル エンディアンになります (IA64 でも IIRC ですが、私は確認していません) が、理想的にBitConverter.IsLittleEndian
はエンディアンが重要かどうかを確認する必要があります。または、直接メモリ アクセスではなくビット シフトなどを使用する必要があります。
protobuf-net (まだコミットされていないビルド) から数行を引用するには:
WriteInt64(*(long*)&value);
if (!BitConverter.IsLittleEndian)
{ // not fully tested, but this *should* work
Reverse(ioBuffer, ioIndex - 8, 8);
}
つまり、エンディアンをチェックし、必要に応じて反転します。
はい、コードはエンディアンに依存していると思います。の値はb
、リトル エンディアン プロセッサでは最下位バイトになり、ビッグ エンディアン プロセッサでは最上位バイトになります。これを見やすくするために、16 進数に切り替えましょう。
using System;
class Test
{
unsafe static void Main()
{
int a = 0x12345678;
short b = *(short*)&a;
Console.WriteLine(b.ToString("x"));
}
}
私のx86ボックスでは、「5678」が出力され、最下位バイトが値の「開始」にあったことを示していますa
. ビッグエンディアン モード (おそらく Mono) で実行されているプロセッサで同じコードを実行すると、"1234" が出力されると思います。
私が知る限り、C# と共通言語インフラストラクチャの仕様のどちらにも、ポインター ベースのビット演算と数学演算のエンディアン要件はありません。CLI は、MSIL 実行可能ファイルに格納されたバイナリ データはリトル エンディアン形式でなければならないと述べています。また、ドキュメントの一般的なドリフトは、特別な状況を除いて、コードが特定のメモリ表現 (パックまたはアンパック配列などを含む) に依存してはならないことを示しています。
C# でポインターのスウィズリングを行うべきではありません。コードが何をするかを尋ねる前に、コードをコンパイルしてみる必要があります。