環境:HP-UX11
文字:S-JIS
文字だろうと、10進数だろうと、メモリ上は 0 と 1 の羅列である!
という命題の実験をしようとしたところ、想定外の結果が出力されました。。
なぜこのような結果となるのかを教えてください。
#include <stdio.h>
#include <string.h>
int main()
{
char arr_c[6] = {'m','o','r','i','n','\0'};
int* ip;
ip = arr_c;
printf("arr_c :[%d]\n", arr_c ); /* [アドレス1]が出る */
printf("ip :[%d]\n", ip ); /* [アドレス1]が出る */
printf("*ip :[%c]\n", *ip ); /* [m]が出る */
printf("*(ip + 1 ) :[%c]\n", *(ip + 1 ) ); /* [n]が出る */
//ここまでは想定通り
int i_from_ip;
i_from_ip = *ip;
printf("i_from_ip :[%d]\n", i_from_ip ); /* [1836020329]ではなく[1769107309]が出る */
}
文字列"morin"の前半4byte分は、
m==01101101 o==01101111 r==01110010 i==01101001
となり、結果としては1836020329(10進数)が返ってくると思っていましたが、、
実際には、1769107309(10進数)が返ってきました。
これを2進数に置き換えると、
i==01101001 r==01110010 o==01101111 m==01101101
となっており、何故か逆さまに読み取られているようです。
てっきり頭から4byte分が取得されると思ったのですが。。
何卒ご教授の程、お願い致します。
No.2ベストアンサー
- 回答日時:
「エンディアン」の問題です。
http://ja.wikipedia.org/wiki%E3%82%A8%E3%83%B3%E …
たとえば、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 になる、ということになります。
ご丁寧にありがとうございます。
とても勉強になりました。
データ型に関係なく、リニアに処理されるもの、と誤解していたことが判りました。
ありがとうございました。
No.4
- 回答日時:
ちょっと待った.
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数は処理系により異なるので、
その注記を漏らしてしまったのはすみませんでした。
ご回答ありがとうございました。
No.3
- 回答日時:
回答自体は、すでに書かれているようなことになります。
一見すると、メモリ上に、"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変数に入れるのであれば、
リトルエンディアンの考え方のほうがしっくり来ますね。
大変勉強になりました。
ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- ハッキング・フィッシング詐欺 自分のIPアドレスをGoogle検索しようとしたら「数字の羅列(IPアドレス)を装ってあなたの情報を 2 2022/04/08 18:36
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- VPN 接続のたびにIPが変わるVPNサービスが知りたい 2 2022/06/27 02:34
- FTTH・光回線 グローバルIPアドレスの変更について 1 2022/04/23 05:32
- Wi-Fi・無線LAN iPhoneのIPアドレスは機内モードをオンで変わるように、無線ルーターも何かの方法で変更できる? 2 2022/04/02 14:37
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- その他(プログラミング・Web制作) このプログラミング誰か教えてくれませんか 4 2022/04/29 15:56
- その他(インターネット接続・インフラ) アプリ利用者を特定し、裁判に 2 2022/06/09 21:43
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ArduinoのジャイロモジュールMP...
-
C言語をコンパイルするとコンピ...
-
mallocについて
-
gccを行ってもexeファイルが生...
-
c言語
-
C言語 列挙型(enum型)変数について
-
卒業研究でよく分からないとこ...
-
C言語初心者 構造体 課題について
-
C++でデスクトップGUIアプリ開...
-
C言語初心者 構造体 課題について
-
win10で、正確な待ち時間の作り方
-
[C言語]fputsとfprintfの違い
-
VisualStudio2022でC言語プログ...
-
大量のデータを読み込んで表示...
-
C言語初心者 ポインタについて...
-
あなたは、Excelはどうやって学...
-
C言語初心者です、、、お助けく...
-
システムエンジニアの適正について
-
Stuck
-
Notepad++の関数リスト表示の変...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
gccを行ってもexeファイルが生...
-
あなたは、Excelはどうやって学...
-
WindowsのCapsLock(キャップス...
-
質問失礼します。 プログラム言...
-
double型が正常に認識されてい...
-
Notepad++の関数リスト表示でC...
-
どちのほうがすきですか?
-
Stuck
-
Notepad++の関数リスト表示の変...
-
ArduinoでMouse関数を使用して...
-
C言語の関数と配列に関する質問
-
C言語って古いですか?
-
Linuxでの開発環境構築や設定の...
-
Bitcoin、BTCはブロックチェー...
-
C++6.0でのresource.hについて
-
MACで動く実行ファイルをWindow...
-
C言語 列挙型(enum型)変数について
-
c言語
-
大量のデータを読み込んで表示...
-
こんなことてしますか??
おすすめ情報