- ベストアンサー
メモリ上の文字の管理と型変換について
- 文字列"morin"をメモリ上で管理する際に生じる問題について説明します。
- 文字列のメモリ上の配置と、型変換による値の変化について詳しく説明します。
- 文字列"morin"の一部が逆順で読まれる現象が発生する理由を解説します。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
「エンディアン」の問題です。 http://ja.wikipedia.org/wiki%E3%82%A8%E3%83%B3%E3%83%87%E3%82%A3%E3%82%A2%E3%83%B3 たとえば、32bitなintの場合、8bitずつ区切った4バイトに分けて、それをメモリには記憶されているわけですが、 このように8bitを超える複数バイトなデータを、その時、下位から順番に記録するか、上位から順番に記録するか、どちらから記録するかというのが「エンディアン」です。 以下、2進数で書いてもいいのですが、わかりやすさのため16進数で書きます。 32bitので0x12345678 という数値があった場合、これは8ビットずつ区切ると、0x12, 0x34, 0x56, 0x78 という4バイトになります。 これをメモリの下位から0x12, 0x34, 0x56, 0x78 という順番にメモリに記録するのが「ビッグエンディアン」という方式で、 これをメモリの下位から0x78, 0x56, 0x34, 0x12 という順番にメモリに記録するのが「リトルエンディアン」(言い換えれば、上位から0x12, 0x34, 0x56, 0x78 という順番)です。 どちらのメモリアクセス方式かはCPUによって変わってきます。これはどちらが優れているとか劣っているということはなく、単なる「方式の違い」でしかありません。 世間でよく使われている Intel のx86系CPUなどはリトルエンディアン。 たとえば、 > char arr_c[6] = {'m','o','r','i','n','\0'}; これは、16進数で書くと > char arr_c[6] = {0x6d, 0x6f, 0x72, 0x69, 0x6e, 0x00}; に相当しますが、 このならびのメモリを、ビッグエンディアンのシステムで32bit数値として読みとった場合は、32bit値は上位から8bitずつ見ると 0x6d, 0x6f, 0x72, 0x69 になる、すなわち 0x6d6f7269=1836020329 になりますが、 このならびのメモリを、リトルエンディアンのシステムで32bit数値として読みとった場合は、32bit値は上位から8bitずつ見ると 0x69, 0x72, 0x6f, 0x6d になる、すなわち 0x69726f6d=1769107309 になる、ということになります。
その他の回答 (3)
- Tacosan
- ベストアンサー率23% (3656/15482)
ちょっと待った. printf("*ip :[%c]\n", *ip ); /* [m]が出る */ printf("*(ip + 1 ) :[%c]\n", *(ip + 1 ) ); /* [n]が出る */ が, なんで「想定通り」なの? これが本当に「想定通り」なら, その後ろの 「結果としては1836020329(10進数)が返ってくると思っていましたが」 と明らかに矛盾する. これを期待するなら *ip で表示されるのは「i」でないとおかしいよ.
お礼
ipのint型(4byte)隣の文字を出せ! という命令文と解釈していますので、 [m]の4個となりは、[n]と想定した次第です。 とは言え、int型のbyte数は処理系により異なるので、 その注記を漏らしてしまったのはすみませんでした。 ご回答ありがとうございました。
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
回答自体は、すでに書かれているようなことになります。 一見すると、メモリ上に、"mori" ("\x6d\x6f\x72\x69") と並んでいるデータを、数値として扱うと、0x69726f8d になるというのは、不自然に見えますが、これはこれで合理的ではあるのです。 (あくまでも、「これはこれで合理的」なのであって、「この方法だけが合理的」ではありませんが) たとえばあるアドレスから、"\x01\x00\x00\x00" という順番でデータが存在したとします。 これは、(上記の方法で)4bytes の数値として扱うと 0x00000001 になります。(数値としての1) 同じアドレスから、2bytesの数値(たとえば、short)だとすると、0x0001 でやはり、数値としての1です。 同じアドレスから、1byteの数値(たとえば、char )だとすると、0x01 で、やはり、数値としての1です。 こういう風に(オーバーフローがない限り)どの長さで切り取っても同じ数値になるという性質があるわけです。 これが、逆のビッグエンディアンであれば、このメモリの並びを 4bytes の整数としてみれば、0x01000000 = 16777216 2bytes の整数としてみれば、0x0100 = 256 1byte の整数としてみれば、 0x01 = 1 と、データ長により数値がわかってきてしまいます。 こういう点で、リトルエンディアンでも、それなりに合理的ではあるわけです。
お礼
ご回答ありがとうございます。 確かに、int変数をdouble変数に入れるのであれば、 リトルエンディアンの考え方のほうがしっくり来ますね。 大変勉強になりました。 ありがとうございました。
- D-Matsu
- ベストアンサー率45% (1080/2394)
一言でいうと「バイトオーダー」によるものです。
お礼
早速のご回答ありがとうございます! 調べてみて、ソケット通信で今まで考慮していなかったのを知り、青ざめました。 確かに、言われてみればそりゃそうだという内容でした。 ありがとうございました。
お礼
ご丁寧にありがとうございます。 とても勉強になりました。 データ型に関係なく、リニアに処理されるもの、と誤解していたことが判りました。 ありがとうございました。