0

"unsigned short" の配列、つまり C の各要素が 16 ビットです。2 つの "unsigned short" 値をリトル エンディアン順で配列に書き戻す必要があります。つまり、最下位要素が最初に来るということです。たとえば、次の値がある場合:

unsigned int val = 0x12345678;

次のように配列に格納する必要があります。

unsigned short buff[10];
buff[0] = 0x5678;
buff[1] = 0x1234;

原子性の問題がある可能性があるため、値を一度に書き込み、int 値の上位 16 ビットと下位 16 ビットを抽出せずに別々に書き込むコードを作成しました。私のコードは次のようになります。

typedef unsigned int UINT32;
*((UINT32*)(buff)) = (value & 0xffff0000)  + (value & 0xffff);

驚くべきことに、上記のコードは正しく機能し、結果は次のようになります。

buff[0] is 0x5678;
buff[1] is 0x1234;

問題は、示されているように、「unsigned short」値をリトル エンディアンではなくビッグ エンディアンで保存していることです。つまり、ポインターを「unsigned short*」から「unsigned int*」にキャストすると、16 ビット要素が自動的にスワップされます。ここで何が起こっているのか、なぜデータがスワップされるのか知っている人はいますか?

4

1 に答える 1

1

プラットフォームはリトル エンディアン形式でデータを表し、buff を (UINT32 *) にキャストすることで、buff を unsigned int へのポインターとして解釈する必要があることをコンパイラーに伝えています。命令

*((UINT32*)(buff)) = (value & 0xffff0000)  + (value & 0xffff);

「(value & 0xffff0000) + (value & 0xffff) をこの unsigned int (buff) に書き込む」というだけです。それが彼のすることであり、彼がそれをどのように保管するかはあなたの仕事ではありません. どちらが先かはプラットフォームに依存するため、下位または上位の 16 ビットのいずれにもアクセスすることは想定されていません。

あなたが知っているのは、unsigned int として buff にアクセスすると、以前にそこに格納したのと同じ値が得られるということだけですが、特定のバイト順序を想定するのは安全ではありません。

したがって、基本的にコードには未定義の動作があります。

于 2013-09-24T22:19:13.313 に答える