ビッグエンディアンとリトルエンディアンの違いを紹介します。
計算機のCPUにはデータの格納方式の違いにより、ビッグエンディアンとリトルエンディアンの2種類があります。
この記事では、プログラム例を紹介しながら、ビッグエンディアンとリトルエンディアンの違いを紹介します。
Windowsで次のプログラムを作成します。C#のコードを例にしています。
namespace EndiannessTestConsole
{
internal class Program
{
static void Main(string[] args)
{
int value = 0x1A2B3C4D;
byte[] ba = BitConverter.GetBytes(value);
for (int i = 0; i < 4; i++) {
Console.WriteLine("[{0:d}] : {1:X}", i, ba[i]);
}
}
}
}
value変数に 0x1A2B3C4E
の値を代入し、その値を BitConverter.GetBytes()を利用してバイト配列に変換しています。
変換したバイト配列の値を画面に出力しています。
プログラムを実行すると以下の結果になります。
[0] : 4D
[1] : 3C
[2] : 2B
[3] : 1A
#include <iostream>
int main()
{
int value = 0x1A2B3C4D;
unsigned char bytes[sizeof(int)];
for (int i = 0; i < sizeof(int); i++) {
bytes[i] = (value >> (i * 8)) & 0xFF;
}
for (int i = 0; i < sizeof(bytes); i++) {
printf("[%d] : %02X\r\n", i, bytes[i]);
}
}
value変数に 0x1A2B3C4E
の値を代入し、その値を "0x000000FF" でマスクしてunsigned char 変数(バイト型)の配列の最初の要素に代入します。
その後8ビット右にシフトして、"0x000000FF" でマスクしてunsigned char の次の配列の要素に代入します。同様に2回繰り返し、int型の変数を4つのunsigned char 変数に
代入します。
変換したunsigned char配列の値を画面に出力しています。
プログラムを実行すると以下の結果になります。
[0] : 4D
[1] : 3C
[2] : 2B
[3] : 1A
今回のプログラムはWindowsのintelのCPUで実行しています。0x1A2B3C4E
の32ビット整数値の場合、一番最初のバイトは 4D
となり、一番下の桁が最初のバイトになります。
この並びがリトルエンディアンになります。ビッグエンディアンのアーキテクチャの場合は、逆に一番最初のバイトが一番上位の桁になります。
表にすると下図になります。
方式 | byte[0] | byte[1] | byte[2] | byte[3] |
---|---|---|---|---|
リトルエンディアン | 0x4D | 0x3C | 0x2B | 0x1A |
ビッグエンディアン | 0x1A | 0x2B | 0x3C | 0x4D |
方式 | ビット |
---|---|
リトルエンディアン | 0100 1101 0011 1100 0010 1011 0001 1010 |
ビッグエンディアン | 0001 1010 0010 1011 0011 1100 0100 1101 |
Intel CPUではリトルエンディアンですが、IPアドレスのバイトオーダーはビッグエンディアンです。
IPアドレスのバイトオーダーを確認します。
using System.Net;
namespace EndiannessTestConsoleIP
{
internal class Program
{
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("192.168.0.100");
byte[] bytes = ip.GetAddressBytes();
for (int i = 0; i < 4; i++) {
Console.WriteLine("[{0:d}] : {1:X}", i, bytes[i]);
}
}
}
}
IPAddress オブジェクトに 192.168.0.100
のアドレスを設定し、GetAddressBytes() メソッドを呼び出して4バイトのバイト配列に変換します。
変換したバイト配列の値を画面に出力しています。
プログラムを実行すると以下の結果になります。
.で区切られているため、違和感はあまりないですが、int型の整数値とは異なり、上位の桁が先頭のバイトになっていることがわかります。
[0] : C0
[1] : A8
[2] : 0
[3] : 64
byte[0] | byte[1] | byte[2] | byte[3] | |
---|---|---|---|---|
0xC0 | 0xA8 | 0x00 | 0x64 |
ビッグエンディアンのため、ビットは上位の値で左から始まります。
1100 0000 1010 1000 0000 0000 0110 0100 |