2009-07-04 35 views
11

これはANSI Cの問題です。私は次のコードを持っています。wchar_tとwint_t

#include <stdio.h> 
#include <locale.h> 
#include <wchar.h> 

    int main() 
    { 
    if (!setlocale(LC_CTYPE, "")) { 
     printf("Can't set the specified locale! " 
       "Check LANG, LC_CTYPE, LC_ALL.\n"); 
     return -1; 
    } 
    wint_t c; 
    while((c=getwc(stdin))!=WEOF) 
     { 
    printf("%lc",c); 
     } 
    return 0; 
    } 

完全なUTF-8サポートが必要ですが、この最も単純なレベルでも、これを何とか改善できますか?適切な変更を加えたwcharではなく、wint_tが使用されるのはなぜですか?

答えて

3

UTF-8は、Unicodeの可能なエンコードの1つです。これは1文字あたり1,2,3または4バイトを定義します。 getwc()で読み取ると、1〜4バイトをフェッチし、1つのUnicode文字コードポイントwchar(プラットフォームによっては16ビットまたは32ビットの幅も可能)に収まる)を構成します。

しかし、Unicode値は0x0000から0xFFFFまでのすべての値にマップされているため、条件コードまたはエラーコードを返す値はありません(Unicodeが16ビットより大きいと指摘しています。これらの場合surrogate pairsが使用される。しかし、ここでのポイントは、UnicodeがEOFのために何を残さない可能な値の全て使用することである。)

種々のエラーコードは-1にマッピングEOF(WEOF)を含みます。返り値getwc()wcharに入れる場合は、Unicode 0xFFFF文字(これは、とにかく予約済みですが、私は脱出します)と区別する方法はありません。

だから答えは、少なくとも32ビットを保持広いタイプ、wint_t(又はint)を使用することです。これは実際の値の下位16ビットを与え、その範囲外に設定されたビットを持つものは、返される文字以外の何かを意味します。

私たちはいつもwintの代わりにwcharを使用していませんか?ほとんどの文字列関連関数はwcharを使用しています。ほとんどのプラットフォームでは、文字列のサイズがwintの1/2であるため、文字列のメモリフットプリントが小さくなります。 @musiphilがとてもうまく、私はここに拡大しようとするでしょう彼のコメントに入れたよう

+2

UTF-8文字の長さは4バイトで、技術的には5バイトまたは6バイトを取ることもできますが、このような構成は有効なutf8文字ではありません。 – quinmars

+0

まあ、本当です。 0x10000以上の余分なプラン文字に入ると4バイト長になる可能性がありますが、UTF-16を扱う際には代理人になります。質問の範囲外だと思っていました。 5バイトまたは6バイトのシーケンスは可能ですが、5バイト未満で表現でき、品質の低いシリアライザによってのみ生成されます。 – lavinio

+2

あなたの答えはほぼ正しいですが、あなたはあまりにも多くの(platofrm depenent)詳細を提供しています。 'wchar_t'は常に16ビットではありませんが、少なくとも2つのOS /コンパイラの組み合わせを32と考えることができます。 –

15

wint_tは、wchar_tの任意の有効な値を格納することができます。 wint_tは、WEOFマクロの評価結果を引き継ぐこともできます(wchar_tが結果を保持するには狭すぎます)。

+1

ありがとう、ありがとうございます。だから、簡単に言えば、いつwchar_tを使う方が良いでしょうか?いつもwint_tを使わないのはなぜですか? –

+10

'wint_t'は、' int'が 'char'に' wchar_t'をすることです。 getc()は 'int'を返して' EOF'を返すことができるにもかかわらず、狭い文字列に 'int'の配列を使用しません。同様に、 'getwc()'が 'WEIT'を返すために' wint_t'を返しても、ワイド文字列には 'wint_t'の配列を使用しません。 – musiphil

+2

@musiphil:あなたのコメントは答えに値する、それはそれらの間の*概念的な違いについて話す唯一のものです。 – MestreLion

6

は、wint_twchar_t概念差があります。

  • wchar_tはあなたが好む場合文字、またはコードポイントを格納するのに十分な大きさ:

    彼らの異なるサイズは、それぞれが非常に明確なセマンティクスを持っているという事実から派生した技術的な側面です。したがって、それらはであり、符号なしです。事実上すべてのプラットフォームで、8ビットの256値に限定されたcharに似ています。したがって、ワイド文字の文字列の変数は、当然この型の配列またはポインタです。

  • は今どのwchar_tプラス追加ステータスを返すことができるようにする必要があり、その一部の文字列機能を入力します。したがって、返品タイプwchar_tより大きくなければなりません。したがって、wint_tが使用されます。これは任意のワイド文字を表すことができ、WEOFも表現できます。ステータスであれば、のネガティブ(通常は)であるため、wint_tはおそらくで、と署名されています。私はCの標準がの委任ではないので "おそらく"と言う。そうである。しかし、符号に関係なく、ステータス値はの外にある必要があります。の範囲はwchar_tです。それらは戻り値としてのみ有用であり、のような文字はのような文字ではありません。

「クラシック」charintとの類似性は、任意の混乱をクリアするために素晴らしいです:文字列がタイプint []ではない、彼らはchar var[](またはchar *var)です。そして、char"半分のサイズint"であるからではありませんが、これは文字列であるためです。

コードは正しく表示されます。は、の結果を確認するために使用されますので、wint_tです。その値がWEOFではない場合は、wchar_t文字(または文字列配列、ポインタなど)に割り当てても安全です

+1

Hmmmm反対意見:C11 Specは、 'wint_t'は符号付きでも符号なしでもいいと言います。さらに、「マクロの「WEOF」の価値は「EOF」の価値と異なる可能性があり、マイナスである必要はない」と述べている。 – chux

+2

@chux:done ...今、改善されていると思います。 – MestreLion

+2

'wchar_t'は必ずしもコードポイントを格納するのに十分な大きさではありません。特に、Windowsでは16ビットしかありません。つまり、基本多言語面外のコードポイントを表すためにサロゲートペアを使用する必要があります。 – rdb

関連する問題