人工知性を作りたい

私が日々、挑戦したことや学んだことなどを紹介していく雑記ブログです。 (新しいAI技術HTM, 専門の音声信号処理, 趣味のアニメ等も書いてます。)

リトルエンディアンとビッグエンディアン あなたのパソコンはどっち?【C言語・自作プログラム】【超簡単!】

f:id:hiro-htm877:20190601191549p:plain

 

f:id:hiro-htm877:20190601202549p:plain

 

 「リトルエンディアン、ビッグエンディアンって何?」

「自分のパソコンのエンディアンを知りたい!」

 

 

そんな方の疑問に答えます。

 

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

・筆者の小話

ある時、私はバイナリ(byteデータ)の音声データを音声に変換していました。 

ちゃんとプログラミングを組んでいるはずなのに音声がザーッとしか聞こえない!

そこで出会ったのがエンディアン問題です。

どうやら、バイナリデータはビックエンディアンで格納されており、私のパソコンはリトルエンディアンだったため、データの扱い方に失敗していたようだ。

1週間、ずっとイライラしていた問題が1時間ぐらいで解消されました。

皆さんもお気をつけください!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

コードが知りたい方は目次のソースコードへ飛んでください!

本記事のテーマ

【完全初心者向け】リトルエンディアンとビッグエンディアンの理解!

自分のCPUのエンディアンを調べるプログラムの作成!

 

トルエンディアン・ビックエンディアンとは、

今日のプロセッサの多くはバイトアドレッシング方式と呼ばれる方式でメモリをアクセスしに行きます。この方式は、メモリのデータ幅(箱の大きさ)に関係なく、1バイト単位でアドレスをつけていく方式です。1バイトごとにアドレスをつけていくので、メモリの容量はアドレス空間の大きさと同じです。

 

プログラム中では、数値演算はレジスタ長を単位として行われます。32ビットプロセッサなら、一度に32ビットの数値が取り扱います。これは、多くのプロセッサは数値演算を行うとき、レジスタを用いるためです(Load/Store architecture)。一方で、バイトアドレッシング方式の場合 データの格納単位はバイトなので、レジスタの内容をメモリに書き出すときにはバイト単位で行います。すると、次の問題が起こります。

32ビットは4バイトあるけど、どの順番でメモリに書けばいいの?

このとき、「多バイトで構成されるデータをどの順番で格納するか」というのがバイトオーダです。そのため、8ビットメモリと8ビットプロセッサを組み合わせた場合や、ワードアドレッシング方式のプロセッサの場合、バイトオーダはありません(厳密にはウソ)。近年、多くのプロセッサはバイトアドレッシング方式の32ビットプロセッサであるため、バイトオーダの問題はほぼ避けられない問題だと思ってよいでしょう。

ちなみに、バイトオーダのことをエンディアンと呼んだりもします。

(下記サイトから引用)

バイトオーダ - ビッグエンディアン/リトルエディアン

 

トルエンディアン(littele endian

ー 最下位ビットが存在するbyteを低位のアドレスへ格納していく方式(バイナリダンプでは「逆順」で見える)

f:id:hiro-htm877:20190612215922j:plain 

ビックエンディアン(big endian

ー 最上位ビットが存在するbyteを低位のアドレスへ格納していく方式(バイナリダンプでは「正順」で見える)

f:id:hiro-htm877:20190612220313j:plain

エンディアン判定プログラム作成!

アルゴリズム

エンディアン判定プログラム作成

1. intで16進数を宣言

2. char型ポインタにintのアドレスを格納

3. charのポインタの値を表示

int型(32bit→4byte)をchar型(8bit→1byte)に分けることで1byteがどう格納されているかが見える!

エンディアン判定プログラム実装!

1.  int src = 0x01234567;

 ←int型の16進数を宣言

2.  char* src_p;

 ←char型のポインタを宣言

3.  src_p = &src;

 ←char型ポインタにint型のアドレスを格納

4.  printf("0x%x\n", *src_p);

 ←char型ポインタの中身を表示

code
int src = 0x01234567;
    char* src_p;
    
    src_p = &src;
    printf("0x%x\n", src);
    printf("0x%x\n", *src_p);
    printf("0x%x\n", src_p[1]);
出力 

0x1234567

0x67

0x45

完成です!

エンディアン判定プログラムを実装しました。

 

出力を見ると自分のパソコンMacbook pro(CPU=intel)はリトルエンディアンだと分かる。

皆さんも自分のパソコンのエンディアンを確認してみて下さい。

 

main文を含む全ソースコードは以下に示します。 

ソースコード

#include <stdio.h>
void enshu0612(void);
int main() {
    enshu0611();
    return 0;
}
void enshu0612(void){
    int src = 0x01234567;
    char* src_p;
    
    src_p = &src;
    printf("0x%x\n", src);
    printf("0x%x\n", *src_p);
    printf("0x%x\n", src_p[1]);
    
}