搭載しているCPUのバイトオーダーをチェックするプログラムを作成してみました。
C
1int n=1; 2 3if (*(char *)&n) 4 printf("Little endian\n"); 5else 6 printf("Big endian\n");
if(*(char *)&n)
この部分の意味がわかりません。
なんでこれでエンディアンが判別できるのですか??
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
char
は必ず1Byteです(Cではchar
の大きさがByteの定義です)。int
は2Bytes以上です。現在主流のシステム(いわゆるパソコンなど)では1Byteが8bits(8桁の二進数)で、int
は4Bytesですので、それを前提に説明します。
int n = 1;
としたとき、まず、メモリ上のスタック領域に4Bytesの領域が連続して確保されます。仮に0x4000番地のアドレスから連続して取られたとしましょう。
番地 | 0x4000 | 0x4001 | 0x4002 | 0x4003 |
---|---|---|---|---|
メモリ上の状態 | (確保) | (確保) | (確保) | (確保) |
次に1
という値を入れるのですが、1
は実際は二進数のビット列
[0000 0000 0000 0000 0000 0000 0000 0001]
です(見やすいように4つ毎に空白を入れていますが、意味はありません。以下同じ)。 これを1Byteずつ4つに分割すると、
[0000 0000] [0000 0000] [0000 0000] [0000 0001]
になります。これを先ほど確保した領域に入れていくのですが、リトルエンディアンとビッグエンディアンでは入れ方違います。
- リトルエンディアンは下位から順番に入れていく。
- ビッグエンディアンは上位から順番に入れていく。
つまり、先ほどの確保領域はこのようにになります。
番地 | 0x4000 | 0x4001 | 0x4002 | 0x4003 |
---|---|---|---|---|
リトルエンディアン | 0000 0001 | 0000 0000 | 0000 0000 | 0000 0000 |
ビッグエンディアン | 0000 0000 | 0000 0000 | 0000 0000 | 0000 0001 |
さて、ここで*(char *)&n
を考えます。まず&n
はn
のアドレスです。つまり今回の例で言うと0x4000です。それを(char *)
とchar *
型にキャストしています。つまり、0x4000がもしchar
のポインタだったら?としているわけです。最後に*
がありますので、ポインタの先の値を見に来ます。つまり、まとめると、
*(char *)&n
はn
のアドレスをchar
のポインタと見なしたときのポインタ先の値
ということです。char
のポインタと見なしているため、最終的な値もchar
型です。そして、char
は1Byetしかないため、1Byteしか見に行きません。
番地 | 0x4000 | 0x4001 | 0x4002 | 0x4003 |
---|---|---|---|---|
リトルエンディアンでの(char *) | 0000 0001 | (見ない) | (見ない) | (見ない) |
ビッグエンディアンでの(char *) | 0000 0000 | (見ない) | (見ない) | (見ない) |
こうして、*(char *)&n
は、リトルエンディアンでは1
、ビッグエンディアンでは0
であることがわかります。if文での条件分岐は0
以外ならその後の文、0
ならelseへという動きなので、それぞれリトルエンディアンである。ビッグエンディアンであると表示されることになります。
1Byteが8bitsではないシステムやintが4Bytesではないシステムでも上の確保領域などの範囲が異なるだけで同じ動作になります。
投稿2016/12/17 10:43
総合スコア21735
0
1バイトの値は00からFFまでで、256通りの数を表せます。整数型で表せる値はは256通りより多いのが普通ですので、コンピュータ内部では複数のバイトを並べて表します。では、たとえば74565
は16進数では0x12345
ですが、4バイトで表すにはどういう順番でバイトを並べればよいでしょう。
00 01 23 45
の順に並べる (ビッグエンディアンの並べ方)45 23 01 00
の順に並べる (リトルエンディアンの並べ方)
1バイトずつ並べんだデータを最初から見ていったときに、大きい桁のほうのバイトが最初に現れるのがビッグエンディアン、小さい桁のほうのバイトが最初に現れるのがリトルエンディアンです。
さて、ご質問のコードで&n
は変数n
へのポインタですが、n
は整数型であり、複数のバイト (たとえば4バイトや8バイト) で表されます。そのポインタを(char *)
にキャストすれば、1バイトのデータ型であるchar
の配列として扱えますから、内部的にビッグエンディアンとリトルエンディアンのどちらの順序でバイトが並んでいるか見ることができます。
整数1
は16進数で0x00…01であり、複数バイトで表すと最上位桁のバイトは00
、最下位桁バイトは01
となりますから、内部的な並びで最初にくるバイトが00と01のどちらであるかで、エンディアンがわかります。
投稿2016/12/17 10:24
編集2016/12/17 10:43総合スコア4315
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
int
型を16bitとしてchar
は8bit。これをメモリーに配置した時にリトルエンディアンではメモリーの下位(LSB)にはint
の下位8bit、上位には(MSB)にはint
の上位8bitが格納されます。なおビッグエンディアンではそれが逆に。もしint
の1をメモリーに格納した場合、0x0001を格納する訳ですが、上位8bitは0x00,下位8bitが0x01になります。
if文の解釈はint n
のアドレスをchar *
にキャストして、8bitとして読む、その場所はメモリーの下位バイト。その内容が`0'でない場合(つまり'0x01')であればリトルエンディアンであると言う意味です。
投稿2016/12/17 10:07
総合スコア3747
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/12/17 11:52
2016/12/17 11:55
2016/12/17 13:43
2016/12/17 13:45