技術(非IT系)

ビッグエンディアンとは?意味や仕組みをわかりやすく解説!(MSB・LSB・バイトオーダー・メモリ配置など)

ビッグエンディアンの意味と基本原理
当サイトでは記事内に広告を含みます

コンピュータで数値や文字列を扱うとき、同じデータであってもメモリに並ぶ順番が異なることがあります。

この並び順を理解するための重要な考え方が、ビッグエンディアンやリトルエンディアンと呼ばれるバイトオーダーです。

普段は意識する機会が少ないものの、ネットワーク通信、バイナリファイル、組み込み開発、異なるCPU間でのデータ連携では、順序の違いが不具合につながる場合があります。

この記事では、ビッグエンディアンの意味、MSBとLSBの関係、メモリ上の配置、変換方法までを、具体例とともにわかりやすく紹介します。

ビッグエンディアンの意味と基本原理

ビッグエンディアンの意味と基本原理

それではまずビッグエンディアンについて解説していきます。

上位バイトから並べる方式

ビッグエンディアンとは、複数バイトで構成される数値をメモリへ格納するときに、最も大きな桁を表す上位バイトから低いアドレスへ置く方式です。

英語ではBig Endianと表記され、bigは大きい、endは端という意味を持ちます。

たとえば16進数で12345678という32ビットの値がある場合、12、34、56、78の順にメモリへ配置されます。

人間が通常読む数字の並びと近いため、メモリダンプや通信データを目で確認する際に理解しやすいと感じる人も多いでしょう。

32ビット値 12345678 をビッグエンディアンで格納する場合

低いアドレスから順に 12 34 56 78

ここでいう12や34は、16進数2桁で表した1バイト分のデータです。

数値そのものが変化するわけではなく、メモリの各番地にどのバイトを置くかという順番だけが異なります。

バイトオーダーという考え方

バイトオーダーは、2バイト以上の整数、浮動小数点数、アドレス値などを扱うときの並び順です。

1バイトは8ビットであり、1バイトだけの値には並び替える対象がないため、エンディアンは問題になりません。

一方で16ビット、32ビット、64ビットのデータでは、どのバイトを先頭に置くかを決める必要があります。

ビッグエンディアンは上位バイト優先、リトルエンディアンは下位バイト優先と覚えると、基本的な区別がしやすくなります。

項目 ビッグエンディアン リトルエンディアン
低いアドレスに置くバイト 上位バイト 下位バイト
数値 1234 の配置例 12 34 34 12
主な利用例 ネットワーク、通信規約、一部CPU 一般的なPC向けCPU
人が読む順番との近さ 比較的近い メモリ上では逆順に見える

用語の由来と利用場面

エンディアンという名称は、小説ガリヴァー旅行記に登場する卵の割り方に関する対立に由来します。

大きい端から割る側と小さい端から割る側の対立を、コンピュータにおけるデータの並び順へたとえた表現です。

現在では単なる雑学ではなく、データ形式を扱う実務上の用語として定着しています。

ネットワークの送受信、TCPやUDPのヘッダー解析、画像や音声のファイル形式、機器制御用のバイナリ通信などでは、エンディアンの確認が欠かせません。

ビッグエンディアンとリトルエンディアンの違いは、数値の大小やビット数ではありません。

複数バイトのデータをメモリや通信データに並べる順序の違いです。

MSBとLSBの役割

続いてはMSBとLSBの意味を確認していきます。

MSBが示す上位側の情報

MSBはMost Significant Bitの略で、日本語では最上位ビットと呼ばれます。

数値の中で最も大きい桁の重みを持つビットを指し、8ビットの値では通常もっとも左側にあるビットがMSBです。

たとえば2進数10010010では、左端の1がMSBになります。

符号付き整数では、このビットが正負の判定に使われる設計も多く、単に大きな桁というだけではない役割を持ちます。

バイト単位で考える場合は、MSBを含むバイトを上位バイト、またはMost Significant Byteと呼びます。

LSBが示す下位側の情報

LSBはLeast Significant Bitの略で、日本語では最下位ビットです。

8ビット値なら右端のビットがLSBであり、もっとも小さな桁の重みを持ちます。

2進数の末尾にあるため、奇数か偶数かの判定、ビットフラグの操作、ビットシフトの説明などでも頻繁に登場します。

複数バイトの数値においては、LSBを含むバイトが下位バイトです。

ビッグエンディアンではMSB側のバイトを先に置き、リトルエンディアンではLSB側のバイトを先に置きます。

16ビット値 AB CD の場合

上位バイトは AB、下位バイトは CD

ビッグエンディアンでは AB CD、リトルエンディアンでは CD AB の順になります。

ビット順序との違い

MSBとLSBの説明では、ビット順序とバイトオーダーを混同しないことが大切です。

ビッグエンディアンが決めるのは、原則としてバイト単位の並びです。

1バイトの内部でビットを左から右へどう伝送するかという話とは、必ずしも同じではありません。

通信規格によってはビットの送信順序も定義されるため、シリアル通信やビット単位のプロトコルを扱う際には別途仕様書を確認する必要があります。

MSBファーストという表記を見たら、バイト順かビット順かを文脈で見極めることが重要です。

メモリ配置と数値の読み取り

続いてはメモリ上でのデータ配置を確認していきます。

32ビット整数の配置例

32ビット整数は4バイトで構成されます。

値が16進数で0A1B2C3Dの場合、各バイトは0A、1B、2C、3Dに分けられます。

ビッグエンディアンでは低いメモリアドレスから0A、1B、2C、3Dの順に配置されます。

リトルエンディアンでは低いアドレスから3D、2C、1B、0Aの順です。

メモリアドレス ビッグエンディアン リトルエンディアン
1000 0A 3D
1001 1B 2C
1002 2C 1B
1003 3D 0A

メモリビューアで値を観察すると、同じ変数であってもCPUの方式によって見える順番が変わります。

この差を知らずにダンプを読むと、値が壊れているように見えることがあるため注意が必要です。

アドレスと並び順の関係

低いアドレスとは、メモリ空間で先に割り当てられた番地を指します。

ビッグエンディアンでは上位バイトが低い番地に置かれるため、先頭から読み進めると16進数表記の左側から順に確認できます。

これは文字列の先頭から読む感覚に近く、デバッグ時の見通しを良くする要素の一つです。

ただし、どちらの方式が本質的に優れているかは用途によって異なります。

演算効率、既存のCPU設計、周辺機器との互換性、ソフトウェア資産など、複数の事情で採用方式が決まります。

符号付き整数と浮動小数点数

エンディアンの影響は符号なし整数だけに限られません。

符号付き整数やIEEE 754形式の浮動小数点数も、複数バイトで保存される場合にはバイトオーダーの影響を受けます。

浮動小数点数は符号部、指数部、仮数部という内部構造を持ちますが、通常は各ビットを個別に反転するのではなく、データ全体のバイト単位で変換します。

データ型が違っても、送受信するバイト列の順序を仕様どおりにそろえることが基本です。

メモリに見える順番と、デバッガが数値として表示する結果は一致しない場合があります。

デバッガはCPUのエンディアンを考慮して数値化するため、バイト列と整数表示を分けて確認しましょう。

ネットワークバイトオーダーと通信処理

続いてはネットワーク通信におけるビッグエンディアンを確認していきます。

ネットワークバイトオーダーの規則

インターネットで広く使われる通信規約では、複数バイトの数値をビッグエンディアンで送る方式がネットワークバイトオーダーとして定められています。

IPアドレス、ポート番号、パケット長、プロトコルの各種フィールドなどを扱うときに、この規則が関係します。

送信側と受信側のCPUが異なるエンディアンでも、共通の並び順を採用すれば正しくデータを解釈できます。

通信規約が事前に順序を固定するのは、機種ごとの違いを吸収するためです。

ホストバイトオーダーとの変換

ホストバイトオーダーとは、実行中のコンピュータが内部的に使用するバイト順です。

一般的なx86系CPUではリトルエンディアンが使われるため、ネットワークへ数値を送る前に変換が必要になる場面があります。

C言語系のネットワークプログラミングでは、16ビット値を変換する関数や32ビット値を変換する関数が用意されています。

関数名は環境によって馴染みがあるかもしれませんが、重要なのは名称よりも、入力値がホスト順なのかネットワーク順なのかを常に意識することです。

ポート番号 8080 は16進数で 1F90 です。

リトルエンディアンのホストでメモリへ置くと 90 1F になり得ます。

ネットワークへ送るバイト列は 1F 90 にそろえます。

通信不具合の典型例

エンディアン変換を忘れると、ポート番号、データ長、識別番号などが意図しない値として受信されます。

たとえば2バイトの長さ情報を逆順で解釈すると、短いデータが非常に大きなサイズに見えることがあります。

その結果、受信待ちが終わらない、バッファサイズの判定に失敗する、パケットを異常として破棄するといった問題が起こります。

バイナリ通信の不具合では、まず仕様書に記載されたフィールド長とバイトオーダーを照合するのが近道です。

送信データを16進数で出力し、期待するバイト列と1バイトずつ比較すると原因を特定しやすくなります。

変換方法と実装時の注意点

続いてはビッグエンディアンへ変換する方法と注意点を確認していきます。

バイトスワップの基本

リトルエンディアンとビッグエンディアンを変換する処理は、一般にバイトスワップと呼ばれます。

16ビットなら2つのバイトを入れ替え、32ビットなら先頭と末尾、中央の2バイトをそれぞれ入れ替えます。

64ビット値では8バイトを反転させる必要があります。

変換対象は数値の文字列表現ではなく、メモリ上のバイト列です。

文字列の1234を4321へ書き換える処理とは異なるため、混同しないようにしましょう。

データ幅 変換前のバイト列 変換後のバイト列
16ビット AA BB BB AA
32ビット 11 22 33 44 44 33 22 11
64ビット 01 02 03 04 05 06 07 08 08 07 06 05 04 03 02 01

プログラミング言語ごとの考え方

多くのプログラミング言語や標準ライブラリには、指定したエンディアンで整数を読み書きする仕組みがあります。

バイナリデータを扱う場面では、自前でビット演算を書く前に、使用言語のパック、アンパック、バッファ、構造体変換の機能を確認するとよいでしょう。

ライブラリを使う利点は、意図がコードから読み取りやすくなり、ビット演算の書き間違いを減らせる点にあります。

一方で、APIがデフォルトでどちらのバイトオーダーを採用するかは、必ずドキュメントで確認する必要があります。

変換の重複を防ぐ設計

実装時によくある問題は、同じ値を二重に変換してしまうことです。

送信前にネットワーク順へ変換した値を、さらに別の層で変換すると、元の順番へ戻ってしまいます。

反対に、受信後の値をホスト順へ戻さず、そのまま計算に使う問題も起こりがちです。

変換の責任範囲を通信層やデータ変換層に集約する設計にすると、アプリケーション側の処理をシンプルに保てます。

エンディアン変換は送信時と受信時の境界で一度だけ行う考え方が基本です。

どの関数がホスト順を受け取り、どの関数がネットワーク順を返すかを明確に管理しましょう。

ビッグエンディアンの理解を深めるポイント

最後にビッグエンディアンの要点をまとめます。

ビッグエンディアンは、複数バイトの数値において上位バイトを低いメモリアドレスから順に配置する方式です。

MSBは最上位ビット、LSBは最下位ビットを表し、バイト単位では上位バイトと下位バイトの順序を理解する手掛かりになります。

ネットワークバイトオーダーではビッグエンディアンが使われるため、リトルエンディアンの環境で通信処理を行う際には変換が重要です。

メモリ配置、通信仕様、バイナリファイルの3つを確認する習慣を持つと、エンディアンによる不具合を防ぎやすくなります。

数値が想定外に見えるときは、値そのものだけでなく、バイト列の順番にも目を向けてみてください。

ビッグエンディアンの仕組みを押さえておけば、低レベルなプログラム解析からネットワーク開発まで、データの流れをより正確に読み取れるようになるでしょう。