• ベストアンサー

リトルエンディアン、ビッグエンディアンについて

リトルエンディアン、ビッグエンディアンについて 質問があります。 (1)簡単にそのPCがリトルエンディアンなのか、ビッグエンディアン  なのか、分かる方法はありますか?  簡単なCプログラムを書いてメモリ状態をダンプするのが、  一番早いのでしょうか?  それとも、Intel系?モントローラ系?CPUにはあまり詳しくないので、  分かりませんが、これらのどちらかに属していれば決められるので  しょうか?ほかの系とかあるのかな・・・ (2)ネットワークプログラミングをするときに、ビッグエンディアンの  マシンからデータを送出する場合には、htonlなどの関数を使用しなく  ても問題ありませんでしょうか?(ネットワークバイトオーダが  ビックエンディアンであるため)

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.3

(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) とかって定義してあったりして「マジに何もしない」ようになってたりします(笑)

upanepa
質問者

お礼

ご回答ありがとうございます。 コンパイルの時点で、エンディアンを変換するか どうかが決まるのですね。実行時に決まるのかと 思っていました。 エンディアンが異なっても、ソース互換があるという ことですね。(バイナリ互換ではない) 勉強になります。

その他の回答 (4)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

「普通」の処理系なら #3 のコードで判定できますが, ISO C の枠内でいくと判定できない可能性があります. sizeof (short) == 1 である環境の可能性が捨てきれません. まあ, ワードマシンで「エンディアン」を考えてもしょうがないという指摘はありですが, 理論的には「移植性のある (= ISO C の枠内で確実な) 判定方法は存在しない」ということで.

upanepa
質問者

お礼

ご回答ありがとうございます。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.4

追記。 当方の回答で 「リトルエディアン環境でコンパイル&実行するとビッグエディアンに変換し、ビッグエディアン環境でコンパイル&実行すると何もしない関数」が「htonl関数そのもの」 と言いました。これは「送出時の観点」から書いた物です。 「受信時の観点」から書けば 「リトルエディアン環境でコンパイル&実行すると、ビッグエディアンからリトルエディアンに変換し、ビッグエディアン環境でコンパイル&実行すると何もしない関数」が「ntohl関数そのもの」 となります(関数名が違う事に注意) つまり 「送出時は、htonl関数を呼んで送出する」 「受信時は、受信してからntohl関数を呼ぶ」 と言う事になります。 そういう訳で、htonl関数、ntohl関数とは「ネットワークバイトオーダーとローカルバイトオーダーを変換する関数のセット」と言う事になります。 そしてこれは「htonl関数、ntohl関数を呼んでさえおけば、実行するマシンが、リトルエディアンかビッグエディアンか気にする必要はない」と言う事を意味します。 この「実行するマシンが、リトルエディアンかビッグエディアンか気にする必要はない」と言うのが、ANo2の方が書いた >htonlを使った方が、簡単なはずです。 の「簡単」の意味です。

upanepa
質問者

お礼

分かりやすい説明ありがとうございます。 とても勉強になりました!

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.2

> (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; } ---------------------------------------------------------------------- エンディアンの判別プログラムは、こんな感じです。

upanepa
質問者

補足

ご回答ありがとうございます。 判定プログラムありがとうございます。 すごく分かりやすいです。 一点質問なのですが、 >htonlを使った方が、簡単なはずです。 これは具体的にはどのような意味なのでしょうか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

Intel だけど Itanium はバイエンディアン (つまりビッグエンディアン, リトルエンディアンのどっちも使える) です. 他にもいくつかバイエンディアンの CPU があったような気がする. 極端なやつだと「プロセスごとにエンディアンが決められる」ものすらあったような.... ということで, ビッグエンディアンと決めつけるのは危険だと思います.

upanepa
質問者

お礼

ご回答ありがとうございます。 >ビッグエンディアンと決めつけとるのは危険だと思います. 将来の移植なども考慮すると、常にhtonlなどを使用して プログラミングしたほうがよいかもしれないですね

関連するQ&A

  • エンディアンについて

    すみません。 教えてください。 リトルエンディアンからビッグエンディアンに変換しないと いけません。 エンディアンについては勉強したつもりですが、 どうしてもわからないことがあります。 ご存知の方、教えていただせんか? CPUはリトルです。 まず、エンディアンの違いについては 以下のように認識しています。 x = 0xAABBCCDD メモリの配置方法が、 トリルだと DD CC BB AA ビックだと AA BB CC DD だと思っています。32ビットの場合です。 で、これを変換するには、htonlで変換可能だと思っっています。 (試したところ可能でした) で次に、32ビットを超えるデータ、たとえば100バイトとかを mallocにして変数に代入しました。 この時はエンディアン変換(ファイルに出力する際)は必要ないのでしょうか? 試しに出力すると、 x = 0x AA BB CC DD EE FF GG ・・・・・・ZZ (100バイトと仮定) バイナリでの出力結果は AA BB CC DD EE FF GG ・・・・・となっていました。 私の認識だと、本CPUはリトルエンディアンのため、 ZZ ・・・・・・・・ DD CC BB AA (四バイトずつ反転しているデータ) が出力されるものと思っていました。(反転してメモリに格納されるため) リトル/ビックを意識しないといけないのは、 2バイトや4バイトの時のみで、それを超える大きなデータ(100バイト)などは 意識せず、そのままバイナリ出力しても、ビックエンディアンで出力されると いうことでよろしいでしょうか? そうなると、エンディアンってなんだんだ???と混乱しています。 わかりにくい説明で大変申し訳ござませんが、 よろしくお願いいたします。

  • ビックエンディアンで動作するPC

    バイトオーダでビックエンディアンとリトルエンディアンがあるのは知っていますが、 実際にビックエンディアンで動作するPCを見たことがありません。 (といいますかビックエンディアンで動作しているか分かりません) 秋葉原等でビックエンディアンで動作するPC(CPU・マザーボード)は買うことはできるのでしょうか? その場合のOS、Linuxになると思いますがディトリビューションどれがよいのでしょうか? クロスコンパイル環境に興味があり、エンディアンが違うPCでも動作するプログラムを 書いてみたいと興味があり質問させていただきました。

  • ftpでのネットワークバイトオーダーについて

    LinuxとUNIXのマシンでftpでファイルのやり取りをする場合、ftpのヘッダとデータ部分のネットワークバイトオーダーは、ビッグエンディアン or リトルエンディアンのどちらで行なっているのでしょうか? 参考になるURLや書籍等ありましたら教えて下さい。 TCP/IPは、ビッグエンディアンでヘッダ部分のやり取りを行なう。ということはネットでは見つかりましたが、ftpについては今の所、不明です。 申し訳ありませんが、どなたか教えて下さい。

  • インテル VS モトローラ

    こんにちは インテル系とモトローラー系でエンディアン(どちらかがリトル・どちらかがビック)が違うと言うことですが、 データのビットの並びが違うのですか? 例えば0番地のアドレスに1バイト(8ビット)のデータが入ってるとして リトルなら0x55 ビックなら0xAA ということでしょうか? またZ80、SHとかARMとかいっぱいCPUはありますが、これらはどちらの形式なんでしょうか? 比較表(比較表?)などあればお知らせ下さい

  • javaのエラーについて質問

    毎度、お世話になります。 下記のコードに於いて、コメント箇所でエラー(UnsupportedOperationException())が発生します。 Q1)このエラーの原因と、改良をご教授ください。 ============================= import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import java.util.Date; import java.util.Random; public class Main { public static void main(String[] args) { Random random = new Random(); random.setSeed((int) new Date().getTime()); ByteBuffer byteBuffer = ByteBuffer.allocate(10000 * 4); long start = System.currentTimeMillis(); ByteOrder order; ByteBuffer tmpBuffer; int[] ints; IntBuffer intBuffer; long end; // ビックエンディアン order = ByteOrder.BIG_ENDIAN; tmpBuffer = byteBuffer.order(order); ints = tmpBuffer.asIntBuffer().array(); //エラー発生:UnsupportedOperationException() intBuffer = IntBuffer.wrap(ints); System.out.println("ビックエンディアンで実行"); printChunk(random, ints, intBuffer); end = System.currentTimeMillis(); System.out.print("経過時間:"); System.out.println((end - start) + "msec\t"); // リトルエンディアン start = System.currentTimeMillis(); order = ByteOrder.LITTLE_ENDIAN; tmpBuffer = byteBuffer.order(order); ints = tmpBuffer.asIntBuffer().array(); //エラー発生:UnsupportedOperationException() intBuffer = IntBuffer.wrap(ints); System.out.println("リトルエンディアンで実行"); printChunk(random, ints, intBuffer); end = System.currentTimeMillis(); System.out.print("経過時間:"); System.out.println((end - start) + "msec\t"); } ========================================= 以上

    • ベストアンサー
    • Java
  • リトルエンディアン→ビッグエンディアン

    (1)リトルエンディアン typedef struct recvData{  int a;  unsigned char b[16]; unsigned char c[8]; unsigned int d[4]; } recvData_t; recvData_t rData; (2)ビッグエンディアン typedef struct sendData{  int a;  unsigned int b[4]; unsigned int c[2]; unsigned int d[4]; } sendData_t; sendData_t sData; 上記のようなリトルエンディアンの構造体の各メンバのデータを、ビッグエンディアンの構造体の各メンバのデータにそれぞれ格納するには どうしたらよいでしょうか?

  • リトルエンディアンというものでしょうか?使いづらいです。

    VC6で以下のようにメモリ上の4バイトは逆さなのでしょうか? 非常に使いづらいです。 正しく?1を取得する方法が知りたいです。 int a[2] = { 1, 2 }; _asm{ // 2003年頃の本を見ると__asmだし、他ではasmだった。 _asmはVC特有? mov esi, a // メモリ上では 0x01 0x00 0x00 0x00 0x02 0x00 0x00 0x00と逆さに入ってる mov eax, [esi+0]; // eaxが 0x10000000 // eaxには1が入って欲しいのですが無理なのでしょうか? 普通の感覚から考えてビックエンディアンが良いと思うのですが、 リトルエンディアンは何に便利なのでしょうか?

  • ビッグ/リトルエンディアンについて

    現在、ワークステーション(SPARC+Soralis)上でFortranで書かれたプログラムがあります。 それをPC(x86+WindowsXP)の環境へ移行した所、Fortran記録(バイナリ)の内容が、CPUアーキテクチャの絡みでビックエンディアン/リトルエンディアンの問題が発生し、苦労しています。 Windows側で使用しているFortranコンパイラは「富士通 Fortran&C Packege V4.0」です。 PC側でまともにワークステーションのバイナリファイルを読みたいのです。 どなたか対策をご存じの方がいらっしゃいましたら、ぜひ、ご教授ください。 よろしくお願いいたします。

  • リトルエンディアン形式、ビッグエンディアン形式

    仕事上でリトルエンディアン形式、ビッグエンディアン形式を使う?のですが意味がまったく解りません 簡単に言ったら JPEGで容量:1.5M、サイズ:640x640、リトルエンディアン形式 JPEGで容量:1.5M以上、サイズ:639x639、ビッグエンディアン形式 となっています 何をどうすればイイのでしょうか? 初めてなので戸惑ってます ちなみにこの作業はコンテンツ作成です

  • 最近のCPUのほとんどはリトルエンディアンかビッグエンディアンでしょうか?

    2000年あたり以降に出た Windows, Mac, Linuxに使われているCPUのほとんどはリトルエンディアンかビッグエンディアンでしょうか? また、たとえば以下のような方法でエンディアンを調べられると考えていいのでしょうか?(VC++です) #include <windows.h> void GetEndian4(char* c){ unsigned __int32 a=0x03020100; BYTE *b = (BYTE*)&a, i=4; while (i--) c[i]=b[i]; } ////////// const char e[4]={}; GetEndian4( const_cast<char*>(e) ); //eが 0,1,2,3 になればリトルエンディアン //3,2,1,0 になればビッグエンディアン //PDP-エンディアンだと 2,3,0,1 …のはず (または2択ならこれだけでも判断可能…?) short s=1; printf( *(char*)&s ? "リトルエディアン\n" : "ビッグエディアン\n" ); あとここでもアラインメントの問題が絡みますが、このように アラインメントが(2のべき乗だとして)大きいであろう方から小さいであろう方にキャストする分には安全で、逆に sizeof(short) == sizeof(char)*2 として char c[2]={1,0}; short s=*(short*)&c; というのは危険な場合がある、ということでしょうか? また、その場合は たとえばビッグエンディアンなら short s=(c[0]<<8)|c[1]; とすればいいでしょうか?

専門家に質問してみよう