• ベストアンサー

ビット幅とその出力について

C言語を習い始めた者ですが、ビット幅とその出力についてわからないことが二つでてきました。以下のソースコードを見てください。 #include <stdio.h> int main(void) { char ss[] = "ABCDEF"; void *vpt; int idt; vpt = ss; idt = * (char *)vpt; printf("char:%x\n", idt); idt = *(int *)vpt; printf("char:%x\n", idt); return 0; } 出力結果は char:41 char:44434241 となります。 一つ目のわからないことは char:41 についてです。私はchar型のビット幅は8ビットで文字ABの16進数を出力すると予想していました。ところが結果は 文字A の16進数の41のみが出力されました。Aの二進数は 1010、 Bの二進数は1011で それぞれ4ビットずつ持っていて合わせて8ビットになるのでそう考えていました。よくわかりませんが結果から、文字一文字に対して8ビットつまり1バイトに相当するのでしょうか? 二つ目は char:44434241 についてです。一つ目の質問に書いた推測が正しければ1文字を1バイトと考えて16進数にすると Aは41 Bは42 Cは43 Dは44 になります。しかしポインタの先頭のアドレスはAになっているはずなのになぜか出力は char:41424344 ではなくchar:44434241になっています。順序が逆になっているのでしょうか? Cをはじめたばかりなので基本的なところがわかっていないかもしれませんが、説明に不足があればつけたしますのでどうかよろしくお願いします。 

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

  • ベストアンサー
  • os6v100i
  • ベストアンサー率44% (16/36)
回答No.3

まず >char ss[] = "ABCDEF"; ですが、これは 'A','B','C','D','E','F','\0' が配列に格納されます。 'A' = 文字Aを表す文字コード = 0x41です。 0x0Aではありませんし、1011という4ビットの数字でもありません。 従って >idt = * (char *)vpt; >printf("char:%x\n", idt); は、ポインタの指す中身をchar(8bit)として取り出して、int(ここでは32bitかな?)に格納し、16進数で表示していますから、41と表示されます。 続いて、 >char:44434241 の件ですが、ご使用の環境はint型が32bitでintelのx86系でしょうか? >idt = *(int *)vpt; でポインタの指す中身を32bitの整数として取り出している訳なんですが intelのx86系のCPUではリトルエンディアンといって、整数の上位と下位を入れ替えてメモリに配置します。 たとえば 0x12345678 という数値はメモリ上 0x78 0x56 0x34 0x12 と配置されます つまり、0x41 0x42 0x43 0x44 と配置されたデータを整数として表現すると0x44434241となってしまうわけです。 エンディアンについて参考URLいれておきます。

参考URL:
http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%B3%E3%83%87%E3%82%A3%E3%82%A2%E3%83%B3
shomarket
質問者

お礼

ウィキベィアでエイディアンについて読みました。初めてエイディアンという言葉を知りました。私のはご指摘いただいたとおりリトルエイディアンでした。なぜ逆になるのかわからなかったのですがエイディアンの機能について参考URLより確認し理解することができました。本当にありがとうございました。

その他の回答 (4)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

おそらく他の方が回答されている通りだとは思いますが、処理系不明の状況で勝手に決めつけるのは正しい姿勢とはいえません。 一般論で回答すると... > 私はchar型のビット幅は8ビットで文字ABの16進数を出力すると予想していました。 char型のビット幅は処理系定義です。<limits.h>のCHAR_BITマクロを調べてください。出力された41は'A'の値です。ただし、文字コードがASCIIかどうかは分かりません。シフトJISやEUC-JPかもしれませんし、UTF-8かもしれません。TRONコードかもしれません。もっと別の文字コードの可能性もあります。 > Aの二進数は1010、 Bの二進数は1011で それぞれ4ビットずつ持っていて合わせて8ビットになるのでそう考えていました。 処理系に関わらず、そんなことにはなりません。 > 文字一文字に対して8ビットつまり1バイトに相当するのでしょうか? 'A'や'B'のような基本実行文字集合に属している文字は、1バイトに相当します。ただし、8ビットかどうかは(前述の通り)処理系に依存します。つまり、1バイトが8ビットかどうかは処理系に依存します。 > 一つ目の質問に書いた推測が正しければ1文字を1バイトと考えて16進数にすると Aは41 Bは42 Cは43 Dは44 になります。しかしポインタの先頭のアドレスはAになっているはずなのになぜか出力は char:41424344 ではなくchar:44434241になっています。順序が逆になっているのでしょうか? ある型のポインタを、要求する境界調整が異なる型へのポインタにキャストし、参照外しを行った場合の動作は未定義です。バイトオーダー(エンディアン)云々以前に、まったくデタラメの値だったとしても文句はいえません。

shomarket
質問者

お礼

ありがとうございます。処理系によってそれぞれ違うんですね。 なんとなくわかったような気がします。

  • pyonmae
  • ベストアンサー率64% (40/62)
回答No.4

こんにちは。 詳しいお話は他の回答者さんに倣いますが、単純に char ss[] = "VWXYZ"; とかにしてみると、何か見えてくるのではないでしょうか。

  • ann_dv
  • ベストアンサー率43% (528/1223)
回答No.2

2つ目の質問に関しては、No.1さんの言われる通り、リトルエンディアンだからですが、 1つ目の質問に関しては根本的に16進数とASCIIコードを混同されています。 16進数の値:0xABとABのキャラクターコードは全く別な値です。

参考URL:
http://www9.plala.or.jp/sgwr-t/c_sub/ascii.html
回答No.1

 参考URLみるか"エンディアン"で検索して下さい。

参考URL:
http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%B3%E3%83%87%E3%82%A3%E3%82%A2%E3%83%B3