- ベストアンサー
リトルエンディアン、ビッグエンディアンについて
リトルエンディアン、ビッグエンディアンについて 質問があります。 (1)簡単にそのPCがリトルエンディアンなのか、ビッグエンディアン なのか、分かる方法はありますか? 簡単なCプログラムを書いてメモリ状態をダンプするのが、 一番早いのでしょうか? それとも、Intel系?モントローラ系?CPUにはあまり詳しくないので、 分かりませんが、これらのどちらかに属していれば決められるので しょうか?ほかの系とかあるのかな・・・ (2)ネットワークプログラミングをするときに、ビッグエンディアンの マシンからデータを送出する場合には、htonlなどの関数を使用しなく ても問題ありませんでしょうか?(ネットワークバイトオーダが ビックエンディアンであるため)
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
(1) エディアンの判定プログラム short s; char *cp; s=1; cp=(char *)&s; if (*cp) { printf("リトルエディアン\n"); } else { printf("ビッグエディアン\n"); } (2) 移植性を考えるなら「実行環境がどうであっても、ネットワークに送出する段階で、ビッグエディアンでデータを並べるようにコーディングする」のが良いでしょう。 つまり、リトルエディアン、ビッグエディアンどちらのマシンでコンパイル&実行しても、ビッグエディアンでデータを送出するように書く事になります。 言い換えれば「リトルエディアン環境でコンパイル&実行するとビッグエディアンに変換し、ビッグエディアン環境でコンパイル&実行すると何もしない」と言う事です。 そして「リトルエディアン環境でコンパイル&実行するとビッグエディアンに変換し、ビッグエディアン環境でコンパイル&実行すると何もしない関数」が「htonl関数そのもの」なのです。 まとめると「移植性を考えるなら、htonl関数が何もしないと判った上で、htonl関数を呼ぶ」と言う事です。 で、ビッグエディアンのマシン用のコンパイラは、htonl関数は #define htonl(a) (a) とかって定義してあったりして「マジに何もしない」ようになってたりします(笑)
その他の回答 (4)
- Tacosan
- ベストアンサー率23% (3656/15482)
「普通」の処理系なら #3 のコードで判定できますが, ISO C の枠内でいくと判定できない可能性があります. sizeof (short) == 1 である環境の可能性が捨てきれません. まあ, ワードマシンで「エンディアン」を考えてもしょうがないという指摘はありですが, 理論的には「移植性のある (= ISO C の枠内で確実な) 判定方法は存在しない」ということで.
お礼
ご回答ありがとうございます。
- chie65536
- ベストアンサー率41% (2512/6032)
追記。 当方の回答で 「リトルエディアン環境でコンパイル&実行するとビッグエディアンに変換し、ビッグエディアン環境でコンパイル&実行すると何もしない関数」が「htonl関数そのもの」 と言いました。これは「送出時の観点」から書いた物です。 「受信時の観点」から書けば 「リトルエディアン環境でコンパイル&実行すると、ビッグエディアンからリトルエディアンに変換し、ビッグエディアン環境でコンパイル&実行すると何もしない関数」が「ntohl関数そのもの」 となります(関数名が違う事に注意) つまり 「送出時は、htonl関数を呼んで送出する」 「受信時は、受信してからntohl関数を呼ぶ」 と言う事になります。 そういう訳で、htonl関数、ntohl関数とは「ネットワークバイトオーダーとローカルバイトオーダーを変換する関数のセット」と言う事になります。 そしてこれは「htonl関数、ntohl関数を呼んでさえおけば、実行するマシンが、リトルエディアンかビッグエディアンか気にする必要はない」と言う事を意味します。 この「実行するマシンが、リトルエディアンかビッグエディアンか気にする必要はない」と言うのが、ANo2の方が書いた >htonlを使った方が、簡単なはずです。 の「簡単」の意味です。
お礼
分かりやすい説明ありがとうございます。 とても勉強になりました!
- Yanch
- ベストアンサー率50% (114/225)
> (1)簡単にそのPCがリトルエンディアンなのか、ビッグエンディアン > なのか、分かる方法はありますか? リトルエンディアン・ビッグエンディアンがどう言ったものであるか 理解しているなら、その判別プログラムも簡単に書ける事でしょう。 分からない場合は、ウェブで調べると良いです。 たぶん、すぐ見つかります。 ・Wikipedia http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%B3%E3%83%87%E3%82%A3%E3%82%A2%E3%83%B3 > (2)ネットワークプログラミングをするときに、ビッグエンディアンの > マシンからデータを送出する場合には、htonlなどの関数を使用しなく > ても問題ありませんでしょうか?(ネットワークバイトオーダが > ビックエンディアンであるため) htonlなどの関数を使わなくても、ネットワークプログラミングをする事は、 可能では、ありますが、htonlを使った方が、簡単なはずです。 参考までにサンプルコードを挙げてみます。 ---------------------------------------------------------------------- #include <stdio.h> int main(int argc, char *argv[]) { union { unsigned short shortValue; unsigned char charValue[2]; } endianTest; endianTest.shortValue = 0x0102; if (endianTest.charValue[0] = 2) { printf("is LittleEndian\n"); } else { printf("is BigEndian\n"); } return 0; } ---------------------------------------------------------------------- エンディアンの判別プログラムは、こんな感じです。
補足
ご回答ありがとうございます。 判定プログラムありがとうございます。 すごく分かりやすいです。 一点質問なのですが、 >htonlを使った方が、簡単なはずです。 これは具体的にはどのような意味なのでしょうか?
- Tacosan
- ベストアンサー率23% (3656/15482)
Intel だけど Itanium はバイエンディアン (つまりビッグエンディアン, リトルエンディアンのどっちも使える) です. 他にもいくつかバイエンディアンの CPU があったような気がする. 極端なやつだと「プロセスごとにエンディアンが決められる」ものすらあったような.... ということで, ビッグエンディアンと決めつけるのは危険だと思います.
お礼
ご回答ありがとうございます。 >ビッグエンディアンと決めつけとるのは危険だと思います. 将来の移植なども考慮すると、常にhtonlなどを使用して プログラミングしたほうがよいかもしれないですね
お礼
ご回答ありがとうございます。 コンパイルの時点で、エンディアンを変換するか どうかが決まるのですね。実行時に決まるのかと 思っていました。 エンディアンが異なっても、ソース互換があるという ことですね。(バイナリ互換ではない) 勉強になります。