人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

char がマルチバイト文字をどのように認識しているかを的確に説明してくれるサイトを教えてください。
'A'はint型だと認識されるしutf-8ではマルチバイト文字を使いますがそれでもchar型は動きます。
正直もうわけがわかりません。そしてこの質問があまり一般的ではないことにも驚いています。私がgoogleをうまく使いこなせていないだけかもしれませんが。
例)
#include <stdio.h>
int main(){
char s[] = "やさしい世界\n";
while(s[i] != '\0')
putchar(str[i++]);
return 0;
}

//失敗例)
#include <stdio.h>
int main(){
char s[] = "やさしい世界\n";
while(s[i] != '\0'){
printf(",%d : ",i);
putchar(str[i++]);
}
return 0;
}

//ソースここまで
おそらくutf-8の場合最初のバイトを見て判断しているのではないかと思いますがわかりません。
できるだけ詳しくマルチバイト文字が1文字をどのように認識しているか説明してくれるサイトまたは私がウェブで検索するキーワードとなる単語を教えてください。

●質問者: 匿名質問者
●カテゴリ:コンピュータ インターネット
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● 匿名回答1号
ベストアンサー

char は、マルチバイト文字を認識しません。

Programming Place Plus C言語編 第46章 マルチバイト文字


匿名質問者さんのコメント
動くこと自体は質問の例1で確認できます。問題が起こる場合も例2で書きましたので理解できていることがわかってもらえたのではないかと思います。 ではどのように中身が動いているか、あるいはOSが認識しているかというのが知りたいことなのですが。

匿名回答2号さんのコメント
C言語のレイヤではcharは単に1バイト(オクテット)づつ文字列を扱うだけで、マルチバイト文字であるとかUTF-8であるとかは認識していません。(規格上、charが1オクテットでないケースもありますが現在では稀です) Unix系なら、出力されたバイト列は、putchar(ライブラリ) -> write(システムコール) -> OS内のi/oモジュール -> 端末ドライバ というふうに流れてゆきます。最終的に画面に文字を出す端末ドライバの部分で、流れてきたバイト列が解釈され、適切なグリフでもって描画されます。マルチバイト文字が「認識」されるのはその部分ですね。そこに至るまではマルチバイト文字という認識はなくて、単なるバイト列です。 Windowsの場合はOS内に渡った時点でunicodeに変換されるので少し違います。

匿名回答3号さんのコメント
えらく古いときの知識ですね >1号さんの引用ページ (と思ったら、書いたのは2010年。うーむ) >> ちなみに、C言語で扱うマルチバイト文字の中に、0x00 が登場しないことは保証されています。 << UTF-16 とか知らないんだろうか。 で、本題。 「マルチ」「バイト」というくらいだから、「バイト」を表すものが複数集まって初めて意味を成す。 例えば、ローマ字だと思ってごらんなさい。 「やさしい」→「yasasi i」 putchar は、y とか a しか出せないんだけど、結局「yasasi i」って出てくるから意味が取れる。 putchar の間に、別のものを混ぜ込むと、意味が取れなくなる。 「0y1a2s3a4s5i6 7i」 (こっちが質問の失敗例)

匿名質問者さんのコメント
おそらくこの回答が一番私の理解を助けてくれたのではないかと思います。 OSが関わっているのかなどを考えていましたが端末の中で文字列が解釈される、 これが私の知りたいどこで、の答えではないかと思います。 cは単に1バイトづつ処理しているだけなんですね。 なぜこのことが様々の参考書に書かれていないのか、なぜ前例となる質問がとても少ないのかわかりませんが、同じ疑問を持った人が見てくださると嬉しいです

匿名回答1号さんのコメント
3号さんへ UTF-16 の話は、次の章に載ってます。 http://www.geocities.jp/ky_webid/ProgrammingPlacePlus/c/047.html マルチバイト文字とワイド文字は、ややこしいですよね。

2 ● 匿名回答4号

マルチバイト文字といえば(Windows でポピュラーなエンコーディングは)Shift_JIS が思い浮かびますが、これについてはマルチバイト文字用のライブラリ関数を使わなければ、正しい結果が得られません。
ASCII の1文字は1バイトですが、Shift_JIS の1文字は1バイトだったり2バイトだったりするからです。
http://msdn.microsoft.com/ja-jp/library/6y9se58z%28v=vs.90%29.aspx

従って、1バイトずつ「ぶった切る」ような事をすれば、Shift_JIS文字列はもはや Sjift_JIS としての形を為しません。



<以下余談>

1.マルチバイト文字には Shift_JIS も含まれますが、C で扱う Shift_JIS文字列の終端文字は '\0' つまり 0 ですので、「0x00 が登場しない」と言ってしまうと語弊があると思います。
確かに 0 は文字列に含まれないですが(strlen は 0 を数えない)、そう言うならば通常の文字列にも 0x00 は登場しない事になりますから、わざわざ「マルチバイト文字の中に」と断る意味は有りません。

2.ワイド文字は wchar_t型を用います。この「入れ物」には UTF-16 が入れられたり、UTF-32 が入れられたりします(Windows NT では UTF-16、Linux・Mac OS Xでは UTF-32 が入っているようです)。ワイド文字の「ヌル文字」は L'\0' です。
マルチバイト文字とワイド文字は違う話なので、混同しないようにしましょう。

3.ロケール locale についても調べてみると良いでしょう。
http://simd.jugem.jp/?eid=22
http://others2.blog.so-net.ne.jp/2010-09-24

C の char は、それ自体は「単なる1バイトの入れ物」であって、内容値が ASCII なのか Shift_JIS なのか EUC なのか UTF-8 なのかという事には関与していません(そもそも char は整数値型であって文字型ではありません)。
char型領域にある整数値が、どのような地域ルールに従って文字表現されるのか、それを決める環境要素がロケール指定だと考えていただいて差し支えないと思います。

ロケールがどういう働きをするか、ざっと示すと以下のようです(この点は他の回答者様からのご指摘も待ちたいと思います)。

a)アプリケーション側で、使われるロケールを設定しておく
a1)char型領域や wchar_t型領域にあるのはあくまで整数値
a2)シングルバイト文字、マルチバイト文字、ワイド文字などの内容値に合わせたライブラリ関数による文字処理

b)アプリケーションを実行・デバイスに表示(OS の仕事)
b1)アプリケーションでロケール未設定だと、「その地域のロケール」が採用される。
b2)アプリケーションの出力する文字コード値を、ロケールに従って表示する。

4.Windows系の場合、コードページについても調べてみると良いでしょう。これはもはや C の話ではないのですが、文字を最終的に出力する際の文字化けについて語る上では、欠かせない事です。
http://msdn.microsoft.com/ja-jp/library/aa288104%28v=vs.71%29.aspx

関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ