5
#define SwapByte4(ldata) \
   (((ldata & 0x000000FF) << 24) | \
   ((ldata & 0x0000FF00) << 8) | \
   ((ldata & 0x00FF0000) >> 8) | \
   ((ldata & 0xFF000000) >> 24))

その 0x000000FF は何を表していますか? 10 進数の 15 が 16 進数で F として表されることは知っていますが、なぜ << 24 なのですか?

4

4 に答える 4

38

以下は 16 進値 0x12345678 で、バイナリとして書き込まれ、いくつかのビット位置で注釈が付けられています。

|31 24|23 16|15 8|7 ビット 0|
+--------------+---------------+---------------+- --------------+
|0 0 0 1 0 0 1 0|0 0 1 1 0 1 0 0|0 1 0 1 0 1 1 0|0 1 1 1 0 0 0|
+--------------+---------------+---------------+- --------------+

...そしてここに 0x000000FF があります:

+--------------+---------------+---------------+- --------------+
|0 0 0 0 0 0 0|0 0 0 0 0 0 0|0 0 0 0 0 0 0|1 1 1 1 1 1 1|
+--------------+---------------+---------------+- --------------+

したがって、ビットごとの AND は、元の値の下位 8 ビットのみを選択します。

+--------------+---------------+---------------+- --------------+
|0 0 0 0 0 0 0|0 0 0 0 0 0 0|0 0 0 0 0 0 0|0 1 1 1 1 0 0 0|
+--------------+---------------+---------------+- --------------+

...そして、24 ビット左にシフトすると、下位 8 ビットから上位に移動します。

+--------------+---------------+---------------+- --------------+
|0 1 1 1 1 0 0 0|0 0 0 0 0 0 0|0 0 0 0 0 0 0|0 0 0 0 0 0 0|
+--------------+---------------+---------------+- --------------+

...16 進数で 0x78000000 です。

他の部分は、入力の残りの 8 ビット部分で動作します。

  0x12345678
& 0x000000FF
  ----------
  0x00000078 << 24 = 0x78000000 (上記参照)

  0x12345678
& 0x0000FF00
  ----------
  0x00005600 << 8 = 0x00560000

  0x12345678
& 0x00FF0000
  ----------
  0x00340000 >> 8 = 0x00003400

  0x12345678
& 0x00000000
  ----------
  0x12000000 >> 24 = 0x00000012

                   | | ----------
                     0x78563412

したがって、全体的な効果は、32 ビット値ldataを 4 つの 8 ビット バイトのシーケンスと見なし、それらの順序を逆にすることです。

于 2010-10-30T12:19:12.120 に答える
5

This kind of code tends to be used to swap things between big endian and little endian format. There is also a little trick that will convert a word in some known format (lets say, little endian) into whatever endianness the current machine happens to be, and vice versa. That would go something like this:

unsigned long littleEndian;
unsigned char* littleBytes = &littleEndian;
unsigned long result = 0;
for (i = 0; i < 4; i++)
    result += unsigned long(littleBytes[i]) << (8 * i);

This works (assuming I haven't messed it up) because regardless of how bytes are actually stored, shift left is guaranteed to shift towards more significant bits. Converting to a char* allows you to access the bytes in the order they are actually stored in memory. Using this trick you don't need to detect the machine endianness to read/write stuff in a known format. Admittedly you could also just use the standard functions (hton etc.) :P

(Note: You have to be a little careful and cast the char before shifting, otherwise it just overflows all over your shoes. Also, += isn't the only option, |= would probably make more sense but might be less clear if you aren't used to it, I'm not sure)

于 2010-10-30T12:52:27.667 に答える
2

0x000000FFをビットマスクとして見る必要があります。つまり、1 の場合は値ldataが取得され、0 - 0 の場合は取得されます。

ビットマスクを理解するには、バイナリに変換する必要があります。16 進数では非常に簡単です。

16 進 0 = バイナリ 0000 16 進 1 = バイナリ 0001 など。

次にシフトします。シフトは、ソースから正確に 8 ビットのデータを取得し、それを宛先の別の場所に移動することに注意してください。

|ここで、すべてのビットマスク AND 演算に OR 演算があることに注意してください。つまり、0 は 0 のままで、'1' の場合は結果に 1 が含まれます。

それが役に立てば幸い :)

于 2010-10-30T10:59:10.260 に答える
0

データが 0x12345678 として表される 32 ビットの数値であるとします (各数値は 16 進数で 4 ビットです)。

Data & 0x000000FF は、最後の 8 ビット (ビット マスクと呼ばれる) のみを保持することを意味します = 0x00000078

<< 24 は、この値を左に 24 ビット移動することを意味します (78 は位置 24 [0 インデックス] から始まります) = 0x78000000

| | 論理的またはこの場合は単なる追加を意味します

最終結果 = 0x78563412

論理操作の読み取り

于 2010-10-30T12:23:29.603 に答える