基本情報で学ぶエンディアンは、複数バイトのデータをどの順番でメモリに置くかというルールです。ビッグエンディアンは上位バイトから、リトルエンディアンは下位バイトから、小さいアドレスへ順に格納します。
「リトルは逆順」と覚えるだけでは、アドレスの図が逆向きになったり、メモリの内容から数値を求めたりする問題で迷いやすくなります。16進数を2桁ずつに分け、アドレスの小さい側を確認してから並べると、図の向きに左右されずに解けます。
この記事では、ビッグとリトルの違いを表で確認し、格納問題・逆算問題・複数の値を扱うオリジナル問題を解きます。バイト順とビット順、数値そのものとメモリ上の表現の違いも整理していきましょう。
- 16進数2桁を1バイトとして区切る理由
- 上位・下位バイトと小さいアドレスの対応
- バイトを並べ替えてもビットを反転しない理由
- 格納・逆算・値ごとの変換を解く手順
基本情報のエンディアンをバイトとアドレスから理解する

エンディアンは複数バイトの並び順を決める
メモリの内容を見たとき、連続する4バイトが一つの整数なのか、別々の値なのかは、並んだ数字だけでは決まりません。一つの値として読む場合でも、どのバイトを上位として扱うかを決める必要があります。その取り決めがエンディアン、別名バイトオーダーです。
たとえば32ビットの整数は、1バイトを8ビットとする環境では4バイトを使います。4バイトの置き方が変わっても、正しいルールで読み出せば同じ整数を復元できます。見た目の順序が変わることと、保存したい数値が変わることは別です。
MDNのエンディアン解説も、数値を構成するバイトの整理方法として説明しています。この記事では、ビッグエンディアンとリトルエンディアンの二つを中心に、バイト単位でアドレスを指定する例を扱います。
学習の前提となる基数や数値表現は、IPAの基本情報技術者試験シラバスVer.9.2でも整理されています。ここでは進数変換の全体を繰り返すより、すでに表された数値をメモリへどう配置するかに集中しましょう。
16進数2桁が1バイトになる理由

16進数は1桁で0〜15の16通りを表します。2進数では4ビットで16通りを表せるので、16進数1桁は4ビット、2桁は8ビットに対応します。したがって1バイトを8ビットとすると、16進数2桁でちょうど1バイトです。
16進数の整数0x2A7C91E0を4バイトで格納する例なら、まず「2A」「7C」「91」「E0」に分けます。0xは16進数であることを示す表記で、値の桁や保存するバイトには含めません。区切りを先に書くと、1桁単位で逆にしてしまう間違いを防げます。
1バイトに入る符号なし整数の範囲は、16進数で00〜FF、10進数で0〜255です。「7C」は二つの文字に見えても、この例では一つのバイトの値を表します。文字の「7」と「C」を保存する話ではありません。
16進数と2進数の対応を復習するなら、基本情報のn進数と2進数・16進数の変換を先に確認すると、バイトの区切りも追いやすくなります。エンディアンの問題で10進数への変換が求められていなければ、16進数のまま進めて大丈夫です。
| 対象 | 16進数での表し方 | ビット数・バイト数 |
|---|---|---|
| 1桁 | A | 4ビット |
| 2桁 | 2A | 8ビット=1バイト |
| 4桁 | 2A7C | 16ビット=2バイト |
| 8桁 | 2A7C91E0 | 32ビット=4バイト |
上位バイトは値の大小ではなく桁の位置で決まる
普通に書いた整数0x2A7C91E0では、左側の「2A」が最上位バイト、右側の「E0」が最下位バイトです。上位・下位は、そのバイトが数値全体のどの桁を担当するかを表します。バイトの数値が大きいか小さいかを比べているわけではありません。
この例では2AよりE0のほうがバイト単独の数値としては大きいですが、2Aが最上位であることは変わりません。2Aには256の3乗の重み、7Cには256の2乗の重み、91には256の重み、E0には1の重みが付くからです。
ビッグの「大きい」、リトルの「小さい」を、データの中で最大・最小のバイトを探す指示だと思わないようにしましょう。リトルエンディアンで最初に置くのは、数値が最小のバイトではなく、数値全体の最下位バイトです。
MSBとLSBという略語が出たときも文脈が大切です。Most Significant Byte/Least Significant Byteならバイトの上位・下位ですが、Bitを指す場合はビットの上位・下位です。問題文に「バイト」「ビット」「4バイトの整数」などの条件があるかを確認してください。
ビッグとリトルを同じアドレス表で比較する

0x2A7C91E0を、アドレス0x1000から4バイトのメモリに格納してみます。ここで0x1000〜0x1003はデータを置く場所の番号、表の中の2Aなどは各場所に入る値です。アドレスもデータも16進数で書けますが、役割は違います。
ビッグエンディアンでは、最上位バイト2Aを最小アドレス0x1000に置き、その次に7C、91、E0を置きます。リトルエンディアンでは、最下位バイトE0を0x1000に置き、91、7C、2Aと続けます。並べ替わるのはデータで、アドレスの意味は変わりません。
| 方式/アドレス | 0x1000 | 0x1001 | 0x1002 | 0x1003 |
|---|---|---|---|---|
| ビッグエンディアン | 2A | 7C | 91 | E0 |
| リトルエンディアン | E0 | 91 | 7C | 2A |
表を小さいアドレスから読むなら、ビッグは普通に書いた整数のバイト順と同じ、リトルはバイト単位で逆になります。ただし「左から」「右から」は図の描き方に依存します。定義は、最小アドレスに上位と下位のどちらを置くかで押さえましょう。
問題で先頭アドレスをA、オフセットを0、+1、+2、+3と書く場合も同じです。実際の場所はA、A+1、A+2、A+3です。「+1」はアドレスの差であり、データの値を1増やすという意味ではありません。バイトアドレスの条件なら、1進むごとに次の1バイトへ移ります。
図の左右よりアドレスの大小を優先する
次のように、左から大きいアドレスが並ぶ図も作れます。左端が必ず先頭とは限らないため、見た目だけで「リトルだから右から」と決めると誤ります。まず最小アドレスを探し、そこからアドレスが増える向きにたどるのが確実です。
| アドレス | 0x1003 | 0x1002 | 0x1001 | 0x1000 |
|---|---|---|---|---|
| リトルエンディアンの内容 | 2A | 7C | 91 | E0 |
この図は左から見ると2A、7C、91、E0なので、整数の普通の表記と同じに見えます。それでも最小アドレス0x1000には最下位バイトE0が入っているので、リトルエンディアンです。図を左右反転しても、方式が切り替わったわけではありません。
縦の表でも考え方は同じです。小さいアドレスが上なら上から、大きいアドレスが上なら下から、アドレス順にデータを拾います。手書きする際はアドレスの行を先に埋めると、データの順序と図の向きを混同しにくくなります。
番地の求め方まで苦手な場合は、基本情報のアドレス指定方式と実効アドレスの求め方で場所と値を分けて確認できます。アドレス指定方式は「どの場所を参照するか」、エンディアンは「複数バイトをどの重みで読むか」が中心です。
バイト順を変えてもビットや16進数の1桁は反転しない

バイト順の変換では、1バイトの中身はそのまま保ちます。0x2A7C91E0をリトルエンディアンで並べた結果はE0、91、7C、2Aです。16進数の文字をすべて反転した「0E19C7A2」にはなりません。
2Aを2進数で表すと00101010です。ビッグからリトルへバイト順を変えても、この8ビットを01010100へ反転する操作は行いません。ビット反転やビット列の逆順、各ビットを0と1で入れ替えるNOT演算は、それぞれ別の操作です。
1バイトだけの値なら、この記事で扱うバイト順の違いは現れません。0x7Cを1バイトとして格納すると、ビッグでもリトルでも7Cです。ただし同じ数値を2バイトの0x007Cとして格納すると、ビッグは00、7C、リトルは7C、00になります。数値が小さいことと、格納幅が1バイトであることは別です。
シリアル通信の説明で「どのビットを先に送るか」が出てきても、メモリのバイト順とは条件を分けて確認します。「リトルエンディアンだからすべてのビットを逆にする」とは判断できません。問題で何を1単位として入れ替えるのかを、最初に決めておきましょう。
格納幅と数値表現を決めてから並べる
0x3Fを4バイトの符号なし整数として格納するなら、必要な幅に合わせて0x0000003Fと書きます。分割すると00、00、00、3Fなので、ビッグはこの順、リトルは3F、00、00、00です。先頭の0を省略した表記から、勝手に1バイトだと判断しないでください。
負の数の問題でも、順番を決める前に、指定されたビット幅と符号表現に従ってビット列を確定させます。たとえば16ビットの2の補数で−2を表すと0xFFFEです。ビッグではFF、FE、リトルではFE、FFになります。バイト順を変えるだけで正負が変わるわけではありません。
符号や小数の表し方を求める計算と、求めたビット列をバイトに分けて置く操作は段階を分けると分かりやすくなります。補数そのものを復習したい場合は、基本情報の負の数・補数と小数表現を確認してください。
浮動小数点数でも、数値からビット列への符号化と、複数バイトの配置順は別の話です。ここで紹介する整数の並べ方をそのまま「小数点を動かす方法」として使うことはできません。問題文にあるデータ型、幅、読み方の条件をそろえてからエンディアンを適用します。
基本情報のエンディアン問題を格納と逆算の手順で解く

格納問題は4段階で整理する
格納する整数と方式が与えられた問題では、数値を何バイトにするか、どのアドレスから置くか、どちらのバイトを先頭にするかを順に決めます。難しい計算に進む前に条件を整理できれば、選択肢の見た目に引っ張られずに答えを作れます。
4バイトなら16進数8桁、2バイトなら4桁にそろえます。0xと区切り文字は除き、2桁ずつを一つのまとまりにします。
先頭アドレスやオフセットを読み、1バイトごとの場所を先に書きます。図の左右ではなくアドレス値で判断します。
ビッグは最上位から、リトルは最下位から、アドレスが小さい順に置きます。各バイトの内部は変えません。
最小アドレスに入るバイトを確認し、必要なバイト数がそろっているかを数えます。元の値に復元できるかも確かめます。
選択式でも、先に自分の答えを短く書いてから選択肢と照合するのがおすすめです。選択肢には、1桁単位の逆転、2バイトずつの入れ替え、アドレスの向きの取り違えを区別するための並びを作れます。丸暗記した文字列の形より、自分で作った4組の対応を基準にしましょう。
慣れてきたら先頭と末尾を見るだけで候補を絞れますが、最後は中間の順序まで確認します。リトルなら先頭が最下位で末尾が最上位という条件だけでは、中間のバイトが正しく並ぶことまで保証できないからです。
オリジナル問題1で格納順を選ぶ
問題1:32ビットの符号なし整数0x6D20A9F3を、アドレス0x2000からリトルエンディアンで格納します。次の表で、0x2000、0x2001、0x2002、0x2003の順に並ぶものはどれでしょうか。
| 選択肢 | 0x2000 | 0x2001 | 0x2002 | 0x2003 |
|---|---|---|---|---|
| ア | 6D | 20 | A9 | F3 |
| イ | F3 | A9 | 20 | 6D |
| ウ | 3F | 9A | 02 | D6 |
| エ | A9 | F3 | 6D | 20 |
正解はイです。まず6D、20、A9、F3に分け、最下位バイトF3から小さいアドレスへ置きます。その次がA9、20、6Dです。先頭0x2000にF3、末尾0x2003に6Dが来ていることも確認できます。
アは同じ整数をビッグエンディアンで配置した並びです。ウは16進数の1桁まで反転しています。エは2バイトのかたまりを入れ替えただけで、32ビット値のリトルエンディアン配置にはなっていません。どの単位で順序を変えているかを見れば、誤答の理由を説明できます。
追加で、0x2002の1バイトだけを問われたら答えは20です。一つのアドレスを指定する問題では、4バイト全体の整数と、その場所の1バイトを区別しましょう。配置ができても、最後の問いを取り違えると別の答えになります。
メモリから数値を復元する逆算問題

逆算では、すでにメモリへ置かれたバイトを拾って、普通に書く数値の上位から下位へ並べ直します。格納問題とは出発点が反対です。「問題文の16進数を逆にする」のではなく、「アドレス順のバイト列を、指定方式で解釈する」と考えてください。
問題2:アドレス0x3000〜0x3003に次のバイトが入っています。この4バイトを一つの32ビット符号なし整数として読むとき、リトルエンディアンとビッグエンディアンではそれぞれどの数値になるでしょうか。
| アドレス | 0x3000 | 0x3001 | 0x3002 | 0x3003 |
|---|---|---|---|---|
| 格納されたバイト | B8 | 04 | 6F | 12 |
リトルエンディアンでは、最小アドレスのB8が最下位、最大アドレスの12が最上位です。数値を普通に書くために上位から並べると12、6F、04、B8となり、答えは0x126F04B8です。途中の04は1バイトなので、0を消して桁数を変えないようにします。
ビッグエンディアンでは最小アドレスのB8が最上位です。そのまま上位からB8、04、6F、12と読むので、答えは0xB8046F12です。同じ場所に同じバイトが入っていても、解釈のルールが違えば別の整数になります。
復元したリトルの答え0x126F04B8を、もう一度リトルで格納するとB8、04、6F、12に戻ります。逆算の検算では、こうして元のメモリ表へ戻せるかを確認すると安心です。「バイト列は同じなのに数値が違う」という現象も、この問題なら具体的に確かめられます。
2バイトの重みで10進数まで確かめる
数値まで計算する問題では、バイトを並べ直した後に基数の変換を行います。1バイトの値は0〜255なので、隣のバイトに移るごとの重みは256倍です。16進数1桁の重み16と、1バイトの重み256を混同しないようにしましょう。
問題3:最小アドレスから順に01、02という2バイトが格納されています。これを一つの16ビット符号なし整数として読んだときの10進数を、二つの方式で求めてください。
ビッグエンディアンでは上位バイトが01、下位が02なので、16進数は0x0102です。10進数なら1×256+2=258になります。リトルエンディアンでは上位が02、下位が01なので、16進数は0x0201、10進数は2×256+1=513です。
| 解釈 | 上位バイト | 下位バイト | 10進数での値 |
|---|---|---|---|
| ビッグ | 01 | 02 | 1×256+2=258 |
| リトル | 02 | 01 | 2×256+1=513 |
先頭のバイトを必ず重い桁として計算してしまうと、リトルでも258と答えることになります。先に「上位はどちらか」を決め、それから重みを付ける手順を守ってください。問題が16進数の値だけを求めるなら、10進数への計算は不要です。
4バイトなら、最小アドレスから並ぶ値をb0、b1、b2、b3とし、リトルではb0+b1×256+b2×256²+b3×256³と計算できます。ビッグでは重みの向きが反対です。これは暗記用の新しい規則というより、各バイトが担当する桁を式にしたものです。
複数の値は値ごとに区切って変換する

バイト列全体を逆にする方法は、「全体が一つの数値」であるときの話です。別々の整数が連続している場合は、各整数の境界を保ってバイト順を変えます。エンディアンの変換と、配列の要素順を逆にすることは同じではありません。
問題4:二つの16ビット符号なし整数A=0x1357、B=0x2468を、この順に連続して保存します。それぞれをリトルエンディアンで格納したとき、最小アドレスから並ぶ4バイトは何でしょうか。
Aの2バイトは13、57なのでリトルでは57、13です。Bの2バイトは24、68なので68、24です。A、Bの順に置くという条件を保つと、答えは57、13、68、24になります。Aの二つのバイトを並べ終わってから、Bの二つへ進みます。
| 対象 | Aの先頭 | Aの次 | Bの先頭 | Bの次 |
|---|---|---|---|---|
| ビッグで保存 | 13 | 57 | 24 | 68 |
| リトルで保存 | 57 | 13 | 68 | 24 |
4バイト全体を逆にした68、24、57、13では、Bが先、Aが後になってしまいます。一方、一つの32ビット整数0x13572468をリトルで保存する条件なら、68、24、57、13で正しくなります。同じ4バイトでも、値の幅と境界が異なると答えが変わるわけです。
ヘッダーの後にデータが続く形式や、1バイトの項目と2バイトの項目が混じる形式も、項目ごとに考えます。1バイトの項目はそのまま、複数バイトの項目は指定された順序で読みます。仕様が分からないバイト列を見た目だけで一括反転するのは避けましょう。
対称な値では方式を判定できない
0xABBAを2バイトで表すとAB、BAなので、ビッグとリトルで順序が変わります。ところが0xABABなら、どちらでもAB、ABです。16進数の文字列が左右対称かどうかではなく、1バイトずつ区切った列を逆にしたときに同じになるかで判断します。
問題5:一つの16ビット整数0x7777を保存したメモリに77、77が並んでいます。この情報だけでビッグかリトルかを特定できるでしょうか。答えは「特定できない」です。二つのバイトが同じなので、どちらの方式で保存しても同じ並びになるからです。
方式を確かめる教材やテストでは、0x1234のように上位と下位が異なる値を使うと違いが見えます。4バイトなら、2A、7C、91、E0のようにすべて異なる値だと、部分的な入れ替えや境界の取り違えも見つけやすくなります。
ただし、未知のバイト列に2A、7C、91、E0が並んでいるだけでは、元の数値も読み方も決まっていません。既知の数値をどう格納したか、またはファイル・通信の仕様として何が指定されているかという追加条件が必要です。並びだけから「こちらが正しい値」と断定しないことも大切です。
通信やプログラムでは仕様に合わせて読み出す

実務では、ファイルや通信で受け取ったバイト列の規約と、読み出しに使うプログラムの規約をそろえます。保存されたビットが壊れていなくても、読む順序が違えば整数は別の値になります。問題2で二つの数値が出たのと同じ仕組みです。
MicrosoftのWindows Socketsのバイト順説明では、ネットワークバイトオーダーへの変換を扱っています。ただし通信データの中身すべてが一律にビッグエンディアンになるとは限りません。アプリケーションのデータは、その通信・ファイル形式で決めた仕様を確認します。
自分のCPUで整数を保存した並びを、そのまま別の機器へ渡せば必ず通じるとは考えないようにしましょう。送る項目が何バイトで、符号があるか、どちらのバイト順かをそろえる必要があります。受信側の読み方が一致すれば、異なる環境でも同じ数値を復元できます。
JavaScriptのDataViewでも、読み出し時に方式を指定できます。MDNのgetUint32の仕様では、第2引数littleEndianがtrueならリトル、falseまたは省略時はビッグとして、指定した位置から4バイトを符号なし整数として読みます。
| 同じバイト列を読む設定 | 対象バイト列(先頭から) | 16進数で示した結果 |
|---|---|---|
| getUint32(0, false) | B8 04 6F 12 | 0xB8046F12 |
| getUint32(0, true) | B8 04 6F 12 | 0x126F04B8 |
この例では、読み方を変えただけで元のバイト列は変わりません。一方、別の形式へ保存し直すときは、値を正しく復元したうえで、保存先のルールに合うバイト列を作ります。「読むときの解釈」と「データの並べ替え」のどちらを行っているかを分けると、変換の二重適用も防ぎやすくなります。
基本情報の学習では、特定のCPU名だけで方式を決めるより、問題文の指定を優先してください。図のアドレス順、値の幅、符号の有無、問われる対象を順に確認する習慣が、プログラムの仕様を読むときにも役立ちます。
基本情報のエンディアンは幅・アドレス・バイト順でまとめる
エンディアンの問題は、幅をそろえる、16進数を2桁ずつに区切る、最小アドレスを確認する、指定方式で並べるという順で解けます。ビッグは上位バイトから、リトルは下位バイトから、小さいアドレスへ置きます。図の左端や右端という覚え方だけに頼らないようにしましょう。
逆算では、アドレス順に拾ったバイトを数値の上位から並べ直します。各バイトの内部は変えず、複数の値があるときは値ごとの境界を保ちます。最後に格納し直して元の表へ戻るか確かめると、変換と読み取りの両方を検算できます。
この記事のオリジナル問題で手順を確認したら、基本情報の無料過去問演習アプリで学習を続けてみてください。答えだけを覚えるより、各問題で「場所」「1バイトの値」「全体の数値」を分けて書くと、どこで読み違えたかを振り返れます。


コメント