• ベストアンサー

エンディアンの問題

バイナリファイルの記憶の仕方にビッグエンディアンとリトルエンディアンがあります。たとえば16ビットのうちの前半の8ビットと後半の8ビットが逆になっていることだと思います。そこで質問ですが、 ○なぜ、そういう風に分かれているのか。 ○この問題が顕在化するのはどのような場合か。 ○その解決方法は? という点について教えて頂きたいのですが。私の記憶では例えばUnixとDOS(Windows)で逆である(どちらがどちらなのか分かりませんが)ということでした。もし、そのことが問題であれば、解決法としてはとにかく反転すればよいということになるかもしれません。簡易ソフトなどもあるようですし、自分でプログラムを書いたこともあります。もちろんどちらが本当に正しいのか判別できなければなりませんが。

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

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4848/10262)
回答No.1

>○なぜ、そういう風に分かれているのか。 CPUを設計した人がどちらが良いかそれぞれ決めたため。 下位バイトが下位アドレス・・・リトルエンディアン 上位バイトから順にならぶ・・・ビッグエンディアン >この問題が顕在化するのはどのような場合か。 ネットワークで通信する場合や外部ストレージにデータをバイナリで格納する場合。 >○その解決方法は? 各プログラミング言語のライブラリに専用の関数が用意されてます。 htonl,htons,ntohl,ntohsとか。 ネットワークではビッグエンディアンが普通なので、ビッグエンディアンの処理系だとこれらは引数をそのまま返す関数で、リトルエンディアンの処理系だと上位バイトと下位バイトをひっくり返す関数です。 ネットワークや外部ストレージに書くときに、htonlやhtonsを呼べば必ずビッグエンディアンにそろい、読み込んだときはntohl,ntohsを呼べば自分にあったエンディアンになります。 >私の記憶では例えばUnixとDOS(Windows)で逆である OSには関係ありません。エンディアンはCPUで決まります。Pentiumやその互換CPUだとリトルエンディアン。

hoso1093
質問者

お礼

回答有難うございました。 ネットワークではビッグエンディアンなので、それを受け取ったPCは盲目的にひっくり返して処理をするわけですね。 私個人の問題としては、あるデータを購入したのですが、ビッグエンディアン指定となっています。そのデータをPC上のあるソフトで解析したのですが、めちゃくちゃな結果となり、エンディアンの問題だなと直感しました。とにかく反転しなければと思っています。また、ビッグだろうとリトルだろうと、処理系が判断して適宜スルーしたり反転したりするということになると、このような問題はそもそもないとも言えるような気がしますが、区別がつかないのでそこまではいかないということなのでしょうね。

その他の回答 (2)

  • eroermine
  • ベストアンサー率18% (83/444)
回答No.3

他のシステムとバイナリデータ-をやりとりするときは XDRマクロを使えば気にしなくともok

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

「Unix と DOS でエンディアンが逆である」ということはありません. Unix であっても Intel 80386系はリトルエンディアン. 歴史的にいえば, 多分オリジナル UNIX の PDP なんかもリトルエンディアンじゃないかな.

関連する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バイト)などは 意識せず、そのままバイナリ出力しても、ビックエンディアンで出力されると いうことでよろしいでしょうか? そうなると、エンディアンってなんだんだ???と混乱しています。 わかりにくい説明で大変申し訳ござませんが、 よろしくお願いいたします。

  • エンディアン:2バイトのデータをShort intにしたいのですが?

    1.Intelの CPU リトルエンディアンでの、問題です。 バイナリファイルをバイト単位で読込み、これを16ビットの整数にしたいのですが、以下のようにコーディングしましたが、うまくいきません。解決方法をご教示下さい。 char s[2]; short int x;   // 16ビットの整数です // s[0] s[1]に、データを読み込みます。 x = (short)(s[0] + 256 * s[1]); 2.同様の問題で、ビッグエンディアンの場合は、どうすればよいかも、ご教示下さい。 よろしくお願いします。

  • リトルエンディアンの1byteデータのビット割付

    リトルエンディアン方式と聞くと2byteデータだったら上位下位が逆転して メモリに割りついているって認識なんですけども、ビット割付も逆転している認識 で問題ないでしょうか? 例えば、1byteの0x1Fというデータがリトルエンディアン方式のビット割付だった場合 1111 0001という割付になるのでしょうか?

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

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

  • 最近の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]; とすればいいでしょうか?

  • バイナリデータからの値の取得について教えてください

    今、バイナリデータから値を取りだそうとがんばっています。 しかし、うまくいかずに困っています。 困っていることは2点あります。 (1)バイナリデータにはリトルエンディアンで格納していると書いています。 まず、リトルエンディアンで書かれている場合、どのような処理を考えることが必要なのでしょうか? (2)バイナリデータには、 はじめに文字列(char)型4バイトで「RIFF]という値 次に32ビット符号なし整数で4バイトの数字、 次に4052バイトの構造体 などと収納されているようです。 このように入っているデータから値を取得するにはどのようにしたらよいのでしょうか? 全然できなくて困っています。 教えていただけないでしょうか? よろしくお願いいたします。

  • バイナリ表示されたデータを小数にかえるには?

    こんばんわ, 今,ある参考書のファイルで 「0000 1010 1010 1010 1010 1010 1010」 という28ビットのバイナリーデータが小数部分をあらわすとき,それをfloat,もしくはdouble型のxに変換せよ。 という,問題があるのですが,1つ1つ上位ビットから0.5×0+0.25×0+・・・とやっていく方法以外にビット演算子やシフト演算子,関数を使用して簡単にできる方法がありましたら教えてください。 ちなみにC言語で作成しています(データはBIGもしくはLITTLEエンディアンどちらの方法でもかまいません)。

  • バイナリから実数を取得したいのですが・・・

    C++にてバイナリデータから倍精度の浮動小数を取得したいと考えています。 バイナリの中にリトルエンディアン形式で倍精度の浮動小数が64ビット幅に収められています。 これをdouble型の変数に代入したいのですが、どうすれば(できれば簡単な方法で)値を代入できるでしょうか? ご教授お願いします。 データのサンプルを念のために記載させて頂きます。 B2 9C 05 DA 7D 40 6C 3F -> 3.448720745086919e-3

  • index.datの内容について

    windows7でindex.datを調べています。 履歴の日付の項目と思われるところがありまして、その値が 6b62fbe385e1cc01・・・・(1) でした。 色々調べてみると、これはwindowstimeというもの?のようで、 変換が必要みたいでした。 それでDCode(www.digital-detective.co.uk)というソフトを使用してみました。 DCodeの設定ですが、DecodeFormatをWindows:64bit Hex Value Little Endian に設定すると Thu, 02 February 2012 17:37:25 +0900・・・・(2) と、自分がアクセスした日が出力されたように感じます。(おおよそですが) そこで何点か質問があります。 1、このフォーマット(windowstime)とは一体なんですか?  (マイクロソフトが考案したwindwosの独自フォーマットと言ってしまえば、それまでですが・・) 2、計算方法がわからなかったので逆から考えることにして、  (2)をunixtimeに変えてみたら1328171845・・・・(3)  になりました。  つまり1970年1月1日00:00:00(UTC)に(3)秒を足せば良いわけですよね?  しかし(1)からどう計算しても(3)になりません。  unixtimeとは切り離して考えた方が良いのでしょうか?  「前記のソフト使えばいいじゃん。」  ではなく、計算方法が知りたいです。  バイナリを見たり、2進数化もしてみましたが、どーしてもたどり着きません。   どなたか計算方法を教えてください。 3、できればperlでこの数値を変換するプログラムを考えたいのですが、効率が良い  プログラムの参考URLまたは64bit Hex Value Little Endianの理論(?)を使った  特殊なコードがperlに存在するなら、それを教えてもらえないでしょうか? ※お粗末な話ですが、当方あまり英語に自信がありません。調べた限りでは海外のURLには いくつか参考になりそうなネタがあるようですが、うまく翻訳でできず意味もわかりかねます。 「ここを見ろ」的なご意見はご勘弁ください。

  • 「自分でわざと問題を起こす→自分で解決→他から評価される」という言葉は?

    自分で意図的に問題を起こす ↓ 自分で解決 ↓ 他から評価される(ことを目論む) という意味の言葉があったと思うのですが思い出せません。 言葉の前半部分の意味は「自分で問題を起こす」の意で、後半部分は「自分で解決する」の意だったと思います。 お分かりになる方がいらっしゃいましたらご解答宜しくお願いいたします。

専門家に質問してみよう