- ベストアンサー
エンディアンについての質問
- エンディアンについての質問です。リトルエンディアンからビッグエンディアンへの変換について教えてください。
- エンディアンの違いについて認識していますが、32ビット以上のデータのエンディアン変換は必要ないのでしょうか?
- リトルエンディアンとビッグエンディアンの意識すべき範囲について混乱しています。エンディアンについて教えてください。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
C言語で説明しますが、特にC言語を知らなくとも大丈夫だと思います。 まず、C言語では char 1byte整数 short 2byte整数 long 4byte整数 と決まっています。 この場合 char c = 0x12; これに関しては、ビッグエンディアンもリトルエンディアンも関係ありません。 ですから、 char cs[100]; と言うのも、同様にビッグエンディアンもリトルエンディアンも関係ありません。 たぶん、質問者さんが言われている100バイトのデータがこれに該当すると思います。 そして問題なのは、 short s = 0x1234; long l = 0x12345678; など、2バイト以上の型の並び順です。 リトルエンディアンで言えば s を1バイト単位で見た場合、c[0]=0x34,c[1]=0x12となります。 l を1バイト単位で見た場合、c[0]=0x87,c[1]=0x65,c[2]=0x43,c[3]=0x21となります。 逆にビッグエンディアンの場合は s を1バイト単位で見た場合、c[0]=0x12,c[1]=0x34となります。 l を1バイト単位で見た場合、c[0]=0x12,c[1]=0x34,c[2]=0x56,c[3]=0x78となります。 10進数で、たとえてるなら「一、十、百、千」と4桁の10進数があった場合 リトルエンディアンだと並びが、「一、十、百、千」 ビッグエンディアンだと並びが、「千、百、十、一」 になると言うもので、つまり並びの重みの向きが違うと言うものです。 アドレス(番地)は、1バイトごとに付けられます。 つまり、 char a[4];とあり、もしa[0]が0番地とした場合、 a[4]は3番地となります。 そして、4バイト整数は連続した4つの番地を使う訳ですが、この場合の0番地が大きい位なのか、小さい位なのかでビッグエンディアン/リトルエンディアンと呼ばれるようになります。 また、最近では8バイト(64bit)も普通に扱えるようになりましたが、これも考えは同じです。 そして、雑学的なことを書けば、リトルエンディアンのメリットは、たとえばlongで定義したエリアの中身が実際には0か1しか値が入らないと言うケースはしばしば発生します。 それをもし、何か間違ってcharで参照したとしても、それは正確に0か1が参照できるのです。(つまり1バイトに収まる値ならば正しく参照可能) 昔は、このようなことをメモリが少なかったため裏技的にやる人もいましたが、もちろん今ではトラブル以外の何ものでもないため、絶対にやりません。
その他の回答 (6)
- Tacosan
- ベストアンサー率23% (3656/15482)
もはや余談の範疇ですが, 世の中には「PDP エンディアン」のような奴もいるので一筋縄ではいかなかったりします. なんか, もっと変態ちっくなやつもあるみたいだけど. で実行時に「どうしてもエンディアンを知りたい」と思ったら #include <limits.h> union FindLongEndian { unsigned long lval; unsigned char byteorder[sizeof (unsigned long)]; } x; x.lval = 0; for (unsigned int i = 1; i <= sizeof (unsigned long); ++i) { x.lval = (x.lval << CHAR_BIT) + i; } とすれば x.byteorder[] に入ってくれる... かな? ところで「char が 1バイト, short が 2バイト, long が 4バイト」に決まってる言語が想像つかないんだけど, 何かあったっけ?
- kmee
- ベストアンサー率55% (1857/3366)
私が普段使っている、MacOSX(64bitカーネル)のgccでは、sizeof(long)==8 なのですが... <「longは4バイトと決まっている」 さて。 同じmallocでも、 char *buff = malloc(100) ; short * s = (short *) buff ; として s[0]=0x1234 ; とすると、 buff[0]==0x34 ; buff[1]==0x12 ; となります(sizeof(short)==2,リトルエンディアンの場合) これがビッグエンディアンだと buff[0]==0x12 ; buff[1]==0x34 ; となります。 ・buff[0],buff[1]のchar2つが、s[0]のshort一つになる:これがcharが100個か、2個の塊(short)が50個か、ということ。 ・そのどちらに上位が入るか、がエンディアン マス目に書いてみたり、Excelみたいな表に書いてみたりすると、イメージしやすいかもしれません
- D-Matsu
- ベストアンサー率45% (1080/2394)
あー、そういえば質問の例示だと100byte全体で反転してますねぇ>#3 後ろの文章しか読んでませんでした。
- Tacosan
- ベストアンサー率23% (3656/15482)
「4Byteデータ25個のカタマリ」だとすると (4バイトごとに格納されるので) DD CC BB AA HH GG FF EE ... のような気がしますが>#2.
- D-Matsu
- ベストアンサー率45% (1080/2394)
ケースバイケース、としか言いようがありません。 質問のケースでは、「100Byteのデータ」というのが所詮「1Byteデータ100個のカタマリ」でしかないためです。 これが「4Byteデータ25個のカタマリ」であればあなたの想定通りの結果になります。
- Tacosan
- ベストアンサー率23% (3656/15482)
「htonl でビッグエンディアンに変換できる」というのは正しいといえば正しいんだけど, より正確には ホストのバイトオーダーからネットワークバイトオーダーに変換する です. もちろん「ネットワークバイトオーダー」は「ビッグエンディアン」なので, リトルエンディアンのホストで実行すれば結果的に「リトルエンディアンからビッグエンディアンに変換できる」ということにはなります. 後の例は ・「32ビットを超えるデータ、たとえば100バイトとかをmallocにして変数に代入しました。」というのがどのように入れているのかが分からん ・「バイナリでの出力」はどのようにしているのか不明 など, ここには書かれていないことがいくつかあるのでなんとも言えません. 具体的に「こんなコードでこうやったんだけど....」というのが出てくれば言いようもある.
補足
みなさん、ご回答ありがとうございます。 説明不足で申し訳ないです。 >・「32ビットを超えるデータ、たとえば100バイトとかをmallocにして変数に代入しました。」 >というのがどのように入れているのかが分からん ですが、 a[] = {"AA","BB","CC"・・・・・ZZ}(100バイト) char *buff; buff = malooc(100); memcoy(buff, a, 100) として代入しています。 >・「バイナリでの出力」はどのようにしているのか不明 は、 "wb" で開いたfpに、 fwrite(buff, 1, 100, fp) としています。 この時、ファイルには、 AABBCCDD・・・・・ZZと出力されています。 ZZ・・・・・BBAA とは出力されていません。 リトルエンディアンなのに、そのまま出力されている現象が 理解できていません。 ちなみに int32 a = 0xAABBCCDD; とすると、DDCCBBAAと出力されています。 以上、よろしくお願いいたします。
補足
ご回答ありがとうございます。 Tacosanさんに追加で質問を書いて登校してから あっ思いました。結論は以下ということですよね。 間違っていたら、ご指摘ください。 ----------------- 質問のケースでは、「100Byteのデータ」というのが所詮「1Byteデータ100個のカタマリ」でしかないためです。 これが「4Byteデータ25個のカタマリ」であればあなたの想定通りの結果になります。 ----------------- なので、 long int の場合は4バイト確保されているので、 メモリ上には逆に入る。 char *buff に いくらmalloc(1000)をしたところで、 それは1バイトのデータが1000ということなので、 反転されない。(1バイトはそのままメモリに格納されるから) ということですよね? まさに、 --------------------------------- 「100Byteのデータ」というのが所詮「1Byteデータ100個のカタマリ」でしかないためです。 --------------------------------- ということですね。 少しエンディアンについて理解できた気がします。