重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

#include<stdio.h>

int main(void)
{
char x[5] = "亜";

printf("%x %x", *x, *(x + 1));

return 0;
}

全角文字を符号化しようとして上のプログラムを考えましたが
実行結果が 「ffffff88 ffffff9f」となってしまいました。
(SJISでは亜 = 889f)

(1)「88 9f」と表示されないのはなぜですか?
(2)4バイトで表示される理由。char型は1バイトでした。
(3)また、リトルエンディアンなので「9f 88」と
表示されないのはなぜですか。
お願いします。

ソースコード編集 SJIS
OS windows Vista 32bit
CUP intel

A 回答 (3件)

確かに


>(SJISでは亜 = 889f)
ですので、x[0]=0x88 x[1]=0x9fが格納されています。
で、それを表示させようとしているのですが、
x[]は、unsignedが指定されていないchar型つまりsignedですので、
x[0]=0x88=136ではなく-120です。同様に、x[1]=0x9f=159ではなく-97です。
%xは、typeが宣言されてないので、int型つまり32ビット符号有りとみなされて
x[0]=-120=0xffffff88 、 x[1]=-97=0xffffff9fと
intが32ビットであるような環境では、4バイトで表示されます。
88 9fと表示させたければ、xをunsigned charで宣言してください。
printfの中でキャストしても構いません。
シフトJISはエンディアンの概念ではなく、第一バイト、第二バイト(1バイト目、2バイト目)といった呼び方をします。
「'亜'は1バイト目が0x88、2バイト目が0x9f」など。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

なるほど。完全にわかりました。
*x、つまり0x88自体には型がないということですな。
そして0x88は2の補数表現では-120を表す!
そしてprintfの変換指定子%xはint型専用なのですね!
(長さ修飾をしない場合)
ご指摘の通り変更したらうまくいきました。
ありがとうございます。

お礼日時:2009/12/03 00:10

一応念の為:


「unsignedが指定されていないchar型つまりsigned」という表現は正しくありません. 一般的には「ただの char が signed か unsigned か」は環境に依存します.
この質問者の環境では signed ですが.

この回答への補足

0x88の型はありますね。char型ですね。char x[5] = "亜"; は
x[0] = 0x88, x[1] = 0x9f; と代入することと同じだから。x[2] ? x[4]は0。

ここで問題なのはprintfの変換指定子%xに長さ修飾子がないと(そのままだと)
int型として拡張表示してしまうこと。そしてマイナスだから1で拡張される。

例えばint型の上位2バイトを出力しようとしたとき
char型で指定しないと2バイト読んでくれないので
型がないということはあり得ることなのか、と思いました。

補足日時:2009/12/02 23:45
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

よくわかりました。

お礼日時:2009/12/03 00:13

> (1)「88 9f」と表示されないのはなぜですか?


汎整数拡張されるから。
> (2)4バイトで表示される理由。char型は1バイトでした。
汎整数拡張されるから。
汎整数拡張の説明は各種解説サイトに譲ります。(検索したら見つかると思う。)

> (3)また、リトルエンディアンなので「9f 88」と表示されないのはなぜですか。
文字コードとエンディアンは関係ありません。
もし、9fと88が入れ替わったりしたら、それはもはやShift JISでは無くなってしまいます。
(UTF-16の様にエンディアンの概念を持つ文字コードもあるけど、
整数型のエンディアンとはまた別。)
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

汎整数拡張はなかなかむずかしいですね。

文字コードではデータをキャストしたりしないので
使うメリットはないですね。

お礼日時:2009/12/03 00:29

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!