web-dev-qa-db-ja.com

UINT32値をUINT8配列に変換する[4]

私の質問は、UINT32値をUINT8配列[4](C/C++)に、できればエンディアンに依存しない方法でどのように変換するかです。さらに、UINT8配列[4]からUINT32値をどのように再構築して、開始した場所に戻るのですか?

13
Chris

エンディアンとは無関係-バイト配列にはsomeエンディアンが必要であるため、実際には何を意味するのかはわかりません。そうは言っても、以下のoneはあなたの要件に答えなければなりません:

与えられたUINT32 vおよびUINT8 a[4]

「ホスト」エンディアン

(マシンのネイティブバイトオーダーを使用):

UINT8 *vp = (UINT8 *)&v;
a[0] = vp[0];
a[1] = vp[1];
a[2] = vp[2];
a[3] = vp[3];

または:

memcpy(a, &v, sizeof(v));

または:

*(UINT32 *)a = v;

ビッグエンディアン

(別名「ネットワーク注文」):

a[0] = v >> 24;
a[1] = v >> 16;
a[2] = v >>  8;
a[3] = v;

リトルエンディアン

a[0] = v;
a[1] = v >>  8;
a[2] = v >> 16;
a[3] = v >> 24;
21
Alnitak

例えば。このような:

UINT32 value;
UINT8 result[4];

result[0] = (value & 0x000000ff);
result[1] = (value & 0x0000ff00) >> 8;
result[2] = (value & 0x00ff0000) >> 16;
result[3] = (value & 0xff000000) >> 24;

編集:括弧を追加(>>は&よりも優先度が高いようです)

12
Patrick

自分でコーディングしたくない場合は、Cライブラリ関数 htonl() を使用して、32ビットintをネットワークバイトオーダーに変換できます。それらをホストの順序に戻すための関数 ntohl() もあります。

それらがネットワークバイトオーダーになったら、それは単にバイト配列としてint/longにアクセスするだけの問題です。

全体として、それはおそらくあなたの目標を達成するための最もポータブルでテストされた方法です。

2
Timo Geusch

ポインタを使ってそれを行うこともできます。 (これはリトルエンディアンですが、同じ再構築方法を使用する場合は問題ありません)

uint32 in = 0x12345678;
uint8 out[4];
*(uint32*)&out = in;

これにより、uint8のメモリアドレスの後ろの4バイトにuint32の値が割り当てられ、正確に必要な処理が行われます。

逆に行くには:

uint8 in[4] = {0x78, 0x56, 0x34, 0x12};
uint32 out;
out = *(uint32*)&in
1
amrelk