質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アーキテクチャ

アーキテクチャとは、情報システム(ハードウェア、OS、アプリケーション、ネットワーク等)の設計方法、設計思想、設計思想に基づいて構築されたシステム構造をアーキテクチャと呼びます

Q&A

解決済

3回答

5679閲覧

C言語でホストバイトオーダーのチェック

strike1217

総合スコア651

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アーキテクチャ

アーキテクチャとは、情報システム(ハードウェア、OS、アプリケーション、ネットワーク等)の設計方法、設計思想、設計思想に基づいて構築されたシステム構造をアーキテクチャと呼びます

0グッド

2クリップ

投稿2016/12/17 09:27

搭載しているCPUのバイトオーダーをチェックするプログラムを作成してみました。

C

1int n=1; 2 3if (*(char *)&n) 4 printf("Little endian\n"); 5else 6 printf("Big endian\n");

if(*(char *)&n)
この部分の意味がわかりません。
なんでこれでエンディアンが判別できるのですか??

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

charは必ず1Byteです(Cではcharの大きさがByteの定義です)。intは2Bytes以上です。現在主流のシステム(いわゆるパソコンなど)では1Byteが8bits(8桁の二進数)で、intは4Bytesですので、それを前提に説明します。

int n = 1;としたとき、まず、メモリ上のスタック領域に4Bytesの領域が連続して確保されます。仮に0x4000番地のアドレスから連続して取られたとしましょう。

番地0x40000x40010x40020x4003
メモリ上の状態(確保)(確保)(確保)(確保)

次に1という値を入れるのですが、1は実際は二進数のビット列

[0000 0000 0000 0000 0000 0000 0000 0001]

です(見やすいように4つ毎に空白を入れていますが、意味はありません。以下同じ)。 これを1Byteずつ4つに分割すると、

[0000 0000] [0000 0000] [0000 0000] [0000 0001]

になります。これを先ほど確保した領域に入れていくのですが、リトルエンディアンとビッグエンディアンでは入れ方違います。

  • リトルエンディアンは下位から順番に入れていく。
  • ビッグエンディアンは上位から順番に入れていく。

つまり、先ほどの確保領域はこのようにになります。

番地0x40000x40010x40020x4003
リトルエンディアン0000 00010000 00000000 00000000 0000
ビッグエンディアン0000 00000000 00000000 00000000 0001

さて、ここで*(char *)&nを考えます。まず&nnのアドレスです。つまり今回の例で言うと0x4000です。それを(char *)char *型にキャストしています。つまり、0x4000がもしcharのポインタだったら?としているわけです。最後に*がありますので、ポインタの先の値を見に来ます。つまり、まとめると、

*(char *)&nnのアドレスをcharのポインタと見なしたときのポインタ先の値

ということです。charのポインタと見なしているため、最終的な値もchar型です。そして、charは1Byetしかないため、1Byteしか見に行きません。

番地0x40000x40010x40020x4003
リトルエンディアンでの(char *)0000 0001(見ない)(見ない)(見ない)
ビッグエンディアンでの(char *)0000 0000(見ない)(見ない)(見ない)

こうして、*(char *)&nは、リトルエンディアンでは1、ビッグエンディアンでは0であることがわかります。if文での条件分岐は0以外ならその後の文、0ならelseへという動きなので、それぞれリトルエンディアンである。ビッグエンディアンであると表示されることになります。

1Byteが8bitsではないシステムやintが4Bytesではないシステムでも上の確保領域などの範囲が異なるだけで同じ動作になります。

投稿2016/12/17 10:43

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2016/12/17 11:52

すす、素晴らしく分かりやすいです。 ありがとうございます
strike1217

2016/12/17 11:55

ただのchar型のキャストでは、ダメなのですか?? if(*(char)&n) みたいに・・・
raccy

2016/12/17 13:43

`(char)n`とした場合は、nの中身は整数`1`と認識しており、その整数`1`をcharに収まる範囲にしてから(もちろんcharに収まるのでそのまま)入れられる形になるため、リトルエンディアン、ビッグエンディアンに関係無く`1`になります。(char *)はポインタの処理なので、アドレスはアドレスのまま変化が無いのですが、キャストが終わった後の解釈でcharのポインタと見なすから、charの範囲しか見に行かないと言うことです。
strike1217

2016/12/17 13:45

なるほど・・・ (char)ではただの値になってしまうということですね。 分かりました。
guest

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
ikedas

総合スコア4315

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2016/12/17 11:53

「nは整数型であり、複数のバイト (たとえば4バイトや8バイト) で表されます。そのポインタを(char *)にキャストすれば、1バイトのデータ型であるcharの配列として扱えます」 とても分かりやすいです!! ありがとうございます。
guest

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

MasahikoHirata

総合スコア3747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2016/12/17 11:52

ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問