LASSIC Media らしくメディア
ビッグエンディアンとリトルエンディアンの違い|バイト順の基礎
エンディアンとは何か
エンディアン(バイトオーダー)とは、コンピュータが2バイト以上にまたがる数値をメモリやファイル、通信データの中でどの順序に並べて記録するかという取り決めです。1バイトは0x00〜0xffまでの256通りの値しか表せないため、それより大きい整数を扱う際には複数バイトをひとまとめにして格納する必要があり、その並べ方にビッグエンディアンとリトルエンディアンという2つの代表的な方式が存在します。
普段アプリケーションを開発している中でエンディアンを意識する場面は限られているものの、バイナリデータを直接扱う処理や、異なる機器・システム間でデータをやり取りする局面では、この並び順の違いが数値の化けや通信不具合として表面化することがあるものです。発注担当者やプロジェクトマネージャーの立場でも、組み込み機器連携や独自プロトコル設計の話が出た際にエンディアンという言葉の意味を押さえておくと、開発会社との仕様確認がスムーズになるでしょう。
本記事で扱うのは、文字を数値に対応づける文字コードの符号化方式ではなく、すでに決まった数値(整数など)を複数バイトのどの順でメモリ上に並べるかというバイト順そのものがテーマです。文字化けの原因となる文字コードの話とは別のテーマとして切り分けて理解しておくと、混同を避けやすくなります。
ビッグエンディアンとリトルエンディアン
エンディアンの考え方を具体的に理解するために、32ビット(4バイト)の整数 0x12345678 を例に、2つの方式でバイト列がどのように並ぶかを見てみましょう。
| 方式 | 1バイト目 | 2バイト目 | 3バイト目 | 4バイト目 | 特徴 |
|---|---|---|---|---|---|
| ビッグエンディアン | 12 | 34 | 56 | 78 | 先頭に最上位バイト(MSB)を置く。16進数を左から読む人の感覚と一致する |
| リトルエンディアン | 78 | 56 | 34 | 12 | 先頭に最下位バイト(LSB)を置く。x86/x64系CPUで標準的に採用される |
ビッグエンディアンは、数値の最上位バイト(この例では0x12)を先頭、つまりアドレスの若い側に置き、以降は下位バイトへ向かって順に並べる方式です。人間が16進数を左から右に読む感覚と一致するため、バイナリダンプを目視で確認する際に値を読み取りやすいという特徴があります。
一方リトルエンディアンは、最下位バイト(この例では0x78)を先頭に置き、上位バイトほど後ろのアドレスに配置する方式です。加算などの演算を下位バイトから順に処理しやすいという実装上の理由から、多くのCPUアーキテクチャで採用されてきました。
なぜ2つの方式があるのか
エンディアンが1つに統一されていないのは、歴史的にCPUの内部設計や用途に応じて異なる方式が選ばれてきた経緯によるものです。代表的な採用状況は次の通りです。
- x86/x64系CPU: IntelやAMDのプロセッサはリトルエンディアンを採用しており、Windows・Linux・macOSが動く一般的なPCやサーバの多くはリトルエンディアンで数値を扱います。
- ARM系CPU: 双方の方式に対応できる設計(バイエンディアン)を持つものの、モバイル端末や多くの組み込み環境では実運用上リトルエンディアンで動作させる場合がほとんどです。
- 一部のCPUや通信機器: 旧来のメインフレームや一部のネットワーク機器、産業用機器などでは、ビッグエンディアンを採用している場合があります。
ソフトウェアの世界で共通の取り決めとして使われているのが、ネットワークバイトオーダーという考え方です。TCP/IPをはじめとするインターネットの基盤プロトコルでは、ヘッダ内の数値(ポート番号やIPアドレスなど)をビッグエンディアンで表現すると定められており、送信側・受信側のCPUがどちらのエンディアンであっても、通信区間では共通のバイト順に変換してからやり取りする取り決めになっています。
ファイルフォーマットの側でも、エンディアンをあらかじめ規定しているものがあります。たとえばTIFF画像形式は、ファイル先頭の2バイトに「II」(リトルエンディアン、Intel由来)または「MM」(ビッグエンディアン、Motorola由来)という目印を置き、以降のバイト列をどちらの順で読むかを明示する仕組みを持っています。BMP形式は一般にリトルエンディアンでデータを格納するなど、フォーマットごとにエンディアンの取り決めが異なる点も実務で押さえておきたいポイントです。
このように方式が統一されなかった背景には、CPU設計上のトレードオフがあります。リトルエンディアンは、下位バイトのアドレスがそのまま数値の先頭アドレスと一致するため、桁上がりを伴う加算やビット幅の異なる型への変換といった演算を、下位バイトから順に処理しやすいという利点によるものです。一方ビッグエンディアンは、通信のように先頭から順にバイトを読み進める処理や、人がバイナリを目視で確認するデバッグ作業との相性がよく、ネットワーク機器や一部の業務システムで支持されてきた経緯があります。どちらも一長一短があるため、現在に至るまで単一の方式へ収束していないというのが実情です。
実務で問題になる場面
エンディアンの違いが実際の不具合として顕在化しやすいのは、次のような場面です。
- 異なるエンディアンのシステム間でバイナリデータを直接やり取りする場合: 送信側と受信側でバイト順の解釈が食い違うと、同じバイト列でもまったく異なる数値として読み取られてしまいます。
- 独自のバイナリプロトコルや通信仕様を新たに設計する場合: バイト順を仕様書に明記していないと実装者ごとに解釈が割れ、結合テストの段階で数値化けとして発覚することがあるものです。
- 組み込み機器やIoTデバイスとの連携: サーバやPCとは異なるアーキテクチャで動く機器から送られてくるバイナリデータを解析する処理では、機器側のエンディアン仕様を確認せずに実装すると値が正しく読み取れません。
- レガシーなメインフレームや専用機とのファイル連携: 過去に構築されたシステムが出力するバイナリファイルを新しい基盤で読み込む移行案件などで、エンディアンの違いに起因する不具合が起こることがあります。
具体的には、リトルエンディアン環境で作成した0x12345678というバイナリデータを、バイト順の変換をせずにビッグエンディアン環境でそのまま読み込むと、0x78563412という別の数値として解釈されてしまいます。金額や数量、ステータスコードなど意味を持つ数値がこの化けの影響を受けると、システム間連携の不具合としてそのまま現れることになるでしょう。
産業用の通信プロトコルでも、エンディアンの扱いが論点になることがあります。たとえば工場設備やセンサーとの連携で使われるModbusのようなプロトコルは、規格としてはバイト順を規定していても、実装や設定によってバイト単位・ワード単位の入れ替え(バイトスワップ)が必要になる場合があり、機器メーカーごとの実装差を確認せずに接続すると、数値がずれたまま取得され続けるといった不具合につながりかねません。こうした産業機器・IoTゲートウェイとの連携は、Web開発の現場では馴染みが薄い分、見落とされやすい観点だと言えるでしょう。
なお、テキストデータの文字コードにおいても、UTF-16のような複数バイトで1文字を表す符号化方式ではBOM(バイトオーダーマーク)という目印でバイト順を示す仕組みがありますが、これは文字コードの符号化ルールに関する話であり、本記事で扱う数値のバイト順とは別の話題として区別しておくとよいものです。
対策
エンディアンの違いによる不具合を避けるために、実務では次のような対策が取られています。
- テキスト形式でのやり取りを優先する: JSONやXML、CSVのような人が読めるテキスト形式で数値をやり取りすれば、数値は文字列として表現されるため、エンディアンの違いを意識する必要自体がなくなります。
- プロトコル設計時にバイト順を明示する: 独自のバイナリプロトコルを設計する場合は、仕様書にビッグエンディアン・リトルエンディアンのどちらを採用するかを明記し、送受信の両実装で統一します。
- ネットワークバイトオーダーへの変換関数を使う: C言語のhtonl/ntohl(host to network long / network to host long)のような、ホスト側のエンディアンとネットワークバイトオーダー(ビッグエンディアン)を相互変換する関数を使うと、CPUのエンディアンに依存せず正しい数値に変換できます。
- シリアライズ用のライブラリ・フォーマットを利用する: Protocol BuffersやMessagePack、Apache Avroといったシリアライズの仕組みは、内部でバイト順の差異を吸収する実装になっているため、自前でバイト順を管理せずに済みます。
どの対策を選ぶかは、やり取りする相手システムの制約や性能要件によって変わるものですが、まずは自分たちが扱う数値がメモリ上でどう並ぶのかを図でイメージしておくと理解が進みやすいでしょう。テキスト形式は可読性と保守のしやすさに優れる反面、バイナリ形式に比べてデータ量や処理速度の面で不利になりやすいため、高頻度・大容量のセンサーデータ連携など性能が重視される場面では、バイト順を明示したバイナリ形式やシリアライズライブラリを選ぶ判断も必要になります。
図のように、同じ0x12345678という数値でも、先頭バイト(0x00番地)に何が置かれるかは方式によって正反対になります。この違いを踏まえたうえで、社内システムと外部システム、あるいは複数の機器の間でどちらの方式を採用するのかを設計段階で明確に取り決めておくことが、後工程での数値化けを防ぐ近道になります。
まとめ
エンディアンとは、複数バイトからなる数値をメモリやファイル、通信データの中でどの順に並べるかという取り決めであり、先頭に最上位バイトを置くビッグエンディアンと、先頭に最下位バイトを置くリトルエンディアンの2方式が広く使われています。x86/x64系CPUの多くはリトルエンディアンを採用する一方、TCP/IPのネットワークバイトオーダーはビッグエンディアンで規定されているなど、方式が混在している点が実務上の注意点です。
異なるエンディアンの環境同士でバイナリデータを直接やり取りすると、数値が意図しない値に化けてしまうことがあり、独自プロトコルの設計や組み込み・IoT機器との連携、レガシーシステムとのファイル連携といった場面で問題が起こりやすくなります。テキスト形式の利用やバイト順の明示、シリアライズライブラリの活用といった対策を、設計段階から検討しておくことが重要です。
新規のシステム間連携や独自プロトコルの検討にあたっては、やり取りする数値のバイト順をどちらの方式にするか、あるいはテキスト形式を採用してエンディアンを意識せずに済む設計にするかを、要件定義や基本設計の段階で確認しておくと、結合テスト以降の手戻りを防ぎやすくなるでしょう。
特に、社内の標準環境(サーバやPC)とは異なるアーキテクチャの機器・外部システムが関わる連携案件では、エンディアンの取り決めが仕様書に明記されているかどうかを見積もり段階から確認しておくことが、後工程での認識違いを防ぐポイントになります。
相談するメリット
組み込み機器やIoTデバイス、レガシーな専用機など、自社の標準環境とは異なるアーキテクチャを持つシステムとのバイナリ連携は、エンディアンの取り扱いを含めて仕様の詰めが甘いと、結合テストの段階で数値化けとして問題が表面化しやすい領域です。特に社内に組み込み系の知見を持つ担当者が少ない企業では、相手機器のエンディアン仕様の確認や、独自プロトコルのバイト順設計まで手が回らないケースも見られます。LASSICでは、ニアショア開発体制を生かした受託開発により、異機種間通信や組み込み・IoT連携を含むバイナリプロトコルの設計支援、既存の連携処理におけるエンディアン起因の不具合調査まで対応しています。仕様策定や実装でお困りの際は、お気軽にご相談ください。
よくある質問
今どきエンディアンを意識する必要はありますか。
一般的なWebアプリケーション開発でJSONなどのテキスト形式を使っている場合、エンディアンを意識する場面は多くありません。ただし、バイナリファイルの解析、独自の通信プロトコル設計、組み込み機器やIoTデバイスとの連携に携わる際には、押さえておく必要がある知識です。
ビッグエンディアンとリトルエンディアンはどちらが優れていますか。
一方が明確に優れているというものではなく、それぞれ得意とする場面が異なります。ビッグエンディアンは16進数を人が読む順序と一致し可読性に優れる一方、リトルエンディアンは下位バイトから処理する演算と相性がよいとされています。実務では、採用するCPUや準拠するプロトコル・フォーマットの仕様に合わせて選ぶことになるものです。
自分のPCやサーバがどちらのエンディアンか確認する方法はありますか。
一般的なIntel/AMD系のPC・サーバ(x86/x64)であれば、リトルエンディアンで動作しています。厳密に確認したい場合は、プログラミング言語が提供するエンディアン判定用の関数やライブラリ(たとえばPythonのsys.byteorderなど)を使うと、実行環境のエンディアンを取得できます。
開発中にエンディアンの不具合が疑われる場合、どこを確認すればよいですか。
まずは通信やファイルの両端でバイト順の仕様が一致しているかを確認します。特に独自プロトコルや組み込み機器との連携部分では、仕様書にビッグエンディアン・リトルエンディアンのどちらを前提にしているかが明記されているかを見直し、実装側もその前提に沿った変換処理(htonl/ntohlのような関数やライブラリ)を入れているかを点検するとよいでしょう。
著者:テレリモ総研編集部 鈴木 亮佑
バイナリプロトコルの設計や異機種間連携、組み込み・IoT機器とのデータ連携でお困りの際は、ニアショア開発によるコスト最適化と品質確保を両立するLASSICにご相談ください。要件のヒアリングから設計、実装まで伴走いたします。