4

C ++標準での意味がわかりません:

基本ソース文字セット (2.3) にないソースファイル文字は、その文字を指定するユニバーサル文字名に置き換えられます。(実装では、ソース ファイルで実際の拡張文字が検出され、ソース ファイルでユニバーサル文字名として (つまり、\uXXXX 表記を使用して) 表現された同じ拡張文字が存在する限り、任意の内部エンコーディングを使用できます。この置換が生の文字列リテラルで元に戻される場合を除いて、同等に処理されます。)

私が理解しているように、コンパイラーが基本文字セットにない文字を検出した場合、それは単にこの形式'\uNNNN'または'\UNNNNNNNN' の一連の文字に置き換えられます。しかし、この NNNN または NNNNNNNN を取得する方法がわかりません。だからこれは私の質問です:変換を行う方法は?

4

3 に答える 3

3

次の文に注意してください。

物理的なソース ファイルの文字は、必要に応じて実装定義の方法で基本的なソース文字セットにマップされます (行末インジケーターに改行文字を導入します)。

つまり、ファイルを構成する文字またはバイトを実際にどのように解釈するかは、完全にコンパイラ次第です。この解釈を行う際に、基本的なソース文字セットに属する物理文字とそうでない文字を決定する必要があります。キャラクターが属していない場合、それはユニバーサル キャラクター名に置き換えられます (または、少なくとも、あたかもそうであったかのような効果があります)。

これのポイントは、ソース ファイルを非常に小さな文字セットに減らすことです。基本的なソース文字セットには 96 文字しかありません。基本的なソース文字セットに含まれていない文字は、\uまたはU、および一部の 16 進数 ( 0- F) に置き換えられています。

ユニバーサル キャラクター名は、次のいずれかです。

\uNNNN
\UNNNNNNNN

それぞれNが 16 進数です。これらの数字の意味は、§2.3 に記載されています。

ユニバーサル文字名で指定される文字\UNNNNNNNNは、ISO/IEC 10646 での文字の短縮名がNNNNNNNN;である文字です。ユニバーサル文字名で指定された文字\uNNNNは、ISO/IEC 10646 の文字短縮名が である文字です0000NNNN。ユニバーサル文字名の 16 進値がサロゲート コード ポイント ( 0xD800-<code>0xDFFF の範囲内) に対応する場合、プログラムは不正な形式です。

ISO/IEC 10646 標準は Unicode の前に作成され、ユニバーサル文字セット (UCS) を定義しました。コードポイントを文字に割り当て、それらのコードポイントをエンコードする方法を指定しました。その後、Unicode コンソーシアムと ISO グループが力を合わせて Unicode に取り組みました。Unicode 規格は、ISO/IEC 10646 よりもはるかに多く (アルゴリズム、機能文字の仕様など) を規定していますが、現在、両方の規格が同期しています。

NNNNしたがって、またはNNNNNNNNは、その文字の Unicode コード ポイントと考えることができます。

例として、これを含むソース ファイルの行を考えてみます。

const char* str = "Hellô";

ô は基本的なソース文字セットに含まれていないため、その行は内部的に次のように変換されます。

const char* str = "Hell\u00F4";

これにより、同じ結果が得られます。

ユニバーサル文字名が許可されるのは、コードの特定の部分だけです。

于 2013-03-09T14:42:17.590 に答える
2

しかし、この NNNN または NNNNNNNN を取得する方法がわかりません。これが私の質問です。変換を行う方法は?

マッピングは実装定義です (例: §2.3 脚注 14)。たとえば、次のファイルを Latin-1 として保存するとします。

#include <iostream>

int main() {
    std::cout << "Hallö\n";
}

OS Xでコンパイルするとg++、実行後に次の出力が得られます。

Hell�

…しかし、UTF-8 で保存した場合、次のようになります。

Hellö

GCC はシステムの入力エンコーディングとして UTF-8 を想定しているためです。

他のコンパイラは異なるマッピングを実行する場合があります。

于 2013-03-09T15:10:47.323 に答える
1

したがって、ファイルが呼び出されHello°¶.cた場合、その名前を内部で使用すると、コンパイルは次のようになります。

cout << __FILE__ << endl;

コンパイラはに変換Hello°¶.cされHello\u00b0\u00b6.cます。

しかし、私がこれを試してみたところ、g++それはできません...

ただし、アセンブラの出力には次のものが含まれます。

.string "Hello\302\260\302\266.c"
于 2013-03-09T14:17:52.607 に答える