programming:バイトオーダーの変換_バイトスワップ

差分

このページの2つのバージョン間の差分を表示します。

この比較画面にリンクする

両方とも前のリビジョン 前のリビジョン
programming:バイトオーダーの変換_バイトスワップ [2018-06-29 10:23]
Decomo
programming:バイトオーダーの変換_バイトスワップ [2021-03-05 09:32] (現在)
Decomo
行 5: 行 5:
 バイナリデータを扱うプログラムを書く上で、避けて通る事の出来ないバイトオーダーの問題。 バイナリデータを扱うプログラムを書く上で、避けて通る事の出来ないバイトオーダーの問題。
  
-結構頻出問題だと思うのだが、軽くググってみただけではまとまった解説が見つからなかったので、自分用も兼ねてここにまとめて見る。+それなりに頻出問題だと思うのだが、軽くググってみただけではまとまった解説が見つからなかった自分用も兼ねてここにまとめて見る。
  
 ===== バイトオーダーとは何ぞや ===== ===== バイトオーダーとは何ぞや =====
  
-バイトオーダーとは多バイトデータメモリに格納する際のバイトの配置のことで、エンディアンやエンディアンネスとも呼ばれる。+バイトオーダーとは多バイトデータメモリの配置のことで、エンディアンやエンディアンネスとも呼ばれる。
  
-バイトオーダーはコンピュータシステムごとに異なり、現在ではx86系などで使用される**リトルエンディアン(LE)**と、PowerPC((ビッグエンディアンなのはG5のみ。G4まではバイエンディアン。))/MC68000/SPARCなどで使用される**ビッグエンディアン(BE)**の2つに大別される。スマートフォンの台頭で一般的となったARM系はLEで使われることが多い。+バイトオーダーはコンピュータシステムごとに異なり、現在ではx86系などで使用される**リトルエンディアン(LE)**と、PowerPC((ビッグエンディアンなのはG5のみ。G4まではバイエンディアン。))/MC68000/SPARCなどで使用される**ビッグエンディアン(BE)**の2つに大別される。スマートフォンの台頭で一般的となったARM系はLEで使われることが多い。
  
-例えば「0x1234CDEF」という32bit値のメモリ配置は、LE/BEでそれぞれ以下のようになる。+例えば「0x<fc red>12</fc><fc green>34</fc><fc blue>CD</fc><fc orange>EF</fc>」という32ビット値のメモリでの配置は、それぞれのエンディアンで以下のようになる。
  
-^  番地  ^  LE  ^  BE  ^ +^  番地  ^  リトル  ^  ビッグ  ^ 
-|0000|EF|12| +|0000|<fc orange>EF</fc>|<fc red>12</fc>
-|0001|CD|34| +|0001|<fc blue>CD</fc>|<fc green>34</fc>
-|0002|34|CD| +|0002|<fc green>34</fc>|<fc blue>CD</fc>
-|0003|12|EF|+|0003|<fc red>12</fc>|<fc orange>EF</fc>|
  
-リトルエンディアンはデータの下位バイトから、ビッグエンディアンはデータの上位バイトから、それぞれメモリの下位番地より順次配置される。人間から見ればビッグエンディアンの方が分かりやすいが、コンピュータ的にはリトルエンディアンの方が都合がいいらしい。また、データの下位バイトからメモリの下位番地に格納される、という意味ではリトルエンディアンの方が理にかなっていると考えることもできる。+リトルエンディアンはデータの下位バイト、ビッグエンディアンはデータの上位バイトから、それぞれメモリの下位番地より順次配置される。人間から見ればビッグエンディアンの方が分かりやすいが、コンピュータ的にはリトルエンディアンの方が都合がいいらしい。また、データの下位バイトメモリの下位番地に配置する、という意味ではリトルエンディアンの方が理にかなっていると考えられる。
  
 ===== バイトオーダーの違いによる問題 ===== ===== バイトオーダーの違いによる問題 =====
  
-ここでリエンディアン環境上表の番地0000~0003の中身をファイルに書き出す、つまりデータの保存を考えてみよう。何も考えず書き出せば、ファイルの内容は「EFCD3412」となる。+ではここで、データの保存について考えてみる。データの保存とは、とどのつまりメモの内容をファイに書き出すことある。 
 + 
 +0x1234CDEF例でいえば、メモリ番地0000~0003をファイルに書き出すことなりリトルエンディアン環境ではファイルの内容は「EFCD3412」となる。
  
 次に、そのファイルからメモリの状態を復元、つまりデータの読み込みを考える。 次に、そのファイルからメモリの状態を復元、つまりデータの読み込みを考える。
  
-これまた何も考えずにファイル内容をメモリに展開すると、メモリ番地0000から上位番地へ向かって EF CD 34 12 の順で復元される。このメモリ内容は、リトルエンディアン環境ならば**0x1234CDEF**と正しく解釈される、ビッグエンディアン環境では**0xEFCD3412**と解釈され保存時とは異なる値になってしまう。+ファイル内容を先頭から順にメモリに展開すると、番地0000から上位番地へ向かって EF CD 34 12 の順で配置される。このメモリ内容は、リトルエンディアン環境ならば**0x1234CDEF**と正しく解釈される一方、ビッグエンディアン環境では**0xEFCD3412**と解釈され元の値とは異なってしまう。
  
 このように、データ保存環境のエンディアンとデータ読込環境のエンディアンが異なれば、保存時に意図したデータとは異なるデータになってしまう。これでは宜しくない。 このように、データ保存環境のエンディアンとデータ読込環境のエンディアンが異なれば、保存時に意図したデータとは異なるデータになってしまう。これでは宜しくない。
行 45: 行 47:
  
 という処理を施せばよい。 という処理を施せばよい。
- 
-通常はメモリ上のデータのエンディアンを入れ替える 
  
 この処理を行うC言語のマクロは、以下のようになる。一応、1バイト = 8ビットが前提の実装となっているが、それ以外の環境に触れている方はこのページを読まないと思うので気にしない事にする。 この処理を行うC言語のマクロは、以下のようになる。一応、1バイト = 8ビットが前提の実装となっているが、それ以外の環境に触れている方はこのページを読まないと思うので気にしない事にする。
  • programming/バイトオーダーの変換_バイトスワップ.txt
  • 最終更新: 2021-03-05 09:32
  • by Decomo