17

UTF-8 文字列リテラルがあるのに、C11 または C++11 に UTF-8 文字リテラルがないのはなぜですか? 一般的に言えば、文字リテラルは、単一オクテットの UTF-8 コード ポイントと同一の単一の ASCII 文字を表すことを理解していますが、C も C++ もエンコーディングが ASCII である必要があるとは言いません。

基本的に、標準的な権利を読むと'0'、整数 0x30 を表す保証はありませu8"0"んが、char シーケンス 0x30 0x00 を表す必要があります。

編集:

すべての UTF-8 コード ポイントが 1 つの文字に収まるわけではないことは承知しています。このようなリテラルは、単一オクテットのコード ポイント (別名、ASCII) に対してのみ有用であるため、「ASCII 文字リテラル」と呼ぶ方が適切であると思われるため、問題は依然として残っています。UTF-8 文字列リテラルがあるため、質問を UTF-8 で組み立てることを選択しました。移植可能な ASCII 値の保証を想像できる唯一の方法は、文字ごとに定数を記述することです。これは、128 個しかないことを考えるとそれほど悪くはありませんが、それでも...

4

5 に答える 5

10

移植性のない C コードを作成することはまったく問題ありません。これは、そうする多くの正当な理由の 1 つです。システムが ASCII またはそのスーパーセットを使用していると思い込んで、EBCDIC システムでプログラムを実行しようとしないことをユーザーに警告してください。

あなたがとても寛大な気持ちなら、小切手を暗号化することができます。このgperfプログラムは、このようなチェックを含むコードを生成することが知られています。

_Static_assert('0' == 48, "must be ASCII-compatible");

または、C11 より前のコンパイラの場合は、

extern int must_be_ascii_compatible['0' == 48 ? 1 : -1];

C11 を使用している場合は、文字定数にuorプレフィックスを使用できますが、プレフィックスは使用できません...Uu8

/* This is useless, doesn't do what you want... */
_Static_assert(0, "this code is broken everywhere");
if (c == '々') ...

/* This works as long as wchar_t is UTF-16 or UTF-32 or UCS-2... */
/* Note: you shouldn't be using wchar_t, though... */
_Static_assert(__STDC_ISO_10646__, "wchar_t must be some form of Unicode");
if (c == L'々') ...

/* This works as long as char16_t is UTF-16 or UCS-2... */
_Static_assert(__STDC_UTF_16__, "char16_t must be UTF-16");
if (c == u'々') ...

/* This works as long as char32_t is UTF-32... */
_Static_assert(__STDC_UTF_32__, "char32_t must be UTF-32");
if (c == U'々') ...

非常に移植性の高い C で書かれ、非 ASCII システムに移植されたプロジェクトがいくつかあります ()。これにはかなりの量の移植作業が必要であり、コードを EBCDIC システムで実行したいことがわかっていない限り、移植作業を行う本当の理由はありません。

標準について: C 標準を書いている人々は、いくつかのまったく奇妙なものを含め、考えられるすべての C 実装と戦わなければなりません。sizeof(char) == sizeof(long)CHAR_BIT != 8、整数型にトラップ表現があり、sizeof(void *) != sizeof(int *)sizeof(void *) != sizeof(void (*)())、ヒープが割り当てられているなどの既知のシステムがありますva_list。これは悪夢です。

聞いたこともないシステムで動作するコードを書こうとして自分を打ち負かしたり、C 標準の保証を一生懸命探したりしないでください。

たとえば、C 標準に関する限り、以下は の有効な実装ですmalloc

void *malloc(void) { return NULL; }

u8"..."定数は UTF-8 であることが保証されていますが、エンコーディングが文字あたりそれぞれ 16 ビットと 32 ビットであることを除いて保証はなく、実際のエンコーディングは実装によって文書化されなければならないことに注意してくださいu"..."U"..."

要約: 2012 年に ASCII 互換性を想定しても安全です。

于 2012-06-07T20:07:51.727 に答える
8

UTF-8文字リテラルは可変長である必要があります-それらほとんどの場合、charまたはに単一の文字を格納することはできませんwchar。それでは、どのタイプにする必要がありますか?固定サイズの型の配列を除いて、CにもC ++にも可変長型がないため、そのための唯一の妥当な型はconst char *-であり、C文字列はnullで終了する必要があるため、変更されませんなんでも。

編集に関して:

C ++ 11標準からの引用:

基本ソース文字セットのメンバーのグリフは、ASCII文字セットに対応するISO /IEC10646のサブセットから文字を識別することを目的としています。ただし、ソースファイル文字からソース文字セットへのマッピング(変換フェーズ1で説明)は実装定義として指定されているため、基本的なソース文字がソースファイルでどのように表されるかを文書化するための実装が必要です。

(2.3.1の脚注)。

それを保証しないのは当然だと思います。ここでのコメントで述べたように、ほとんどの(またはすべての)主流コンパイラーでは、文字リテラルのASCII性は実装が保証されています。

于 2012-06-07T19:11:15.147 に答える
6

C++ の場合、これはEvolution Working Group issue 119: Adding u8 characterlitersMotivationセクションで次のように説明されています。

文字列リテラルには 5 つのエンコーディング プレフィックス (none、L、u8、u、U) がありますが、文字リテラルには 4 つしかありません。不足しているのは u8 です。ナロー実行文字セットが ASCII でない場合、u8 文字リテラルは、保証された ASCII エンコーディングで文字リテラルを記述する方法を提供します (単一コード単位の u8 エンコーディングは正確に ASCII です)。これらのリテラルのサポートを追加すると、便利な機能が追加され、言語の一貫性が少し向上します。

EWG は、Rapperswil に u8 文字リテラルを追加するというアイデアについて議論し、変更を受け入れました。このホワイト ペーパーでは、その拡張機能の文言を示します。

これは、N4267 の文言を使用してワーキング ドラフトに組み込まれました: u8 文字リテラルの追加。現時点で最新のドラフト標準N4527で文言を見つけることができ、セクションとして2.14.3、単一の UTF-8 に収まるコード ポイントに限定されていると述べていることに注意してください。コード単位:

u8'w' などの u8 で始まる文字リテラルは、UTF-8 文字リテラルと呼ばれる char 型の文字リテラルです。UTF-8 文字リテラルの値は、コード ポイント値が単一の UTF-8 コード単位で表現できる場合 (つまり、US-ASCII 文字である場合)、その ISO10646 コード ポイント値と同じです。複数の c-char を含む UTF-8 文字リテラルは形式が正しくありません。

于 2015-06-16T16:01:50.413 に答える
0

'0'コンパイラがASCII文字0x30として扱われることを信頼できない場合は、static_cast<char>(0x30)代わりに使用できます。

于 2012-06-07T19:33:00.507 に答える