2013-08-24 14 views
5

好奇心の高まりから、本当の根底にあるC++文字列リテラルの種類は何か不思議です。C++の文字列リテラルのタイプ

私が観察していることに応じて、私は異なる結果を得ます。次のような

のtypeid試験:

std::cout << typeid("test").name() << std::endl; 

は私char const[5]を示しています。その(指定されたエラーを参照してください)のような互換性のない型に文字列リテラルを代入しようとすると

wchar_t* s = "hello"; 

私はVS12のインテリセンスからa value of type "const char *" cannot be used to initialize an entity of type "wchar_t *"を取得します。

しかし、私は次の行がVS12に受け入れられるよう、それはconst char *の可能性がどのように表示されていない。私はそれがためにあったように、これは事前にC++ 11の標準規格で許可されたことを読んだことがある

char* s = "Hello"; 

sを変更すると、未定義の動作になりますが、Cとの互換性はありません。私はこれが単にVS12であり、まだC++ 11標準のすべてを実装しておらず、この行は通常エラーになると想定しています。

マルチバイト文字 配列次いでだけ静的記憶域期間と長さの配列を初期化するために使用される:C99規格(from here、6.4.5.5)を読み出す

は、アレイがなければならないことを示唆しています配列を含めるのに十分である。

したがって、C++文字列リテラルの下の型は何ですか?

大変ありがとうございます。

+5

VS12は似ているいくつかの奇妙な方言を話すが、C++、同一ではありません。 –

答えて

8

文字列リテラルのタイプは、実際にはconst char[SIZE]です。ここで、SIZEはヌル終了文字列の長さです。

いつもconst char*が表示されているという事実は、通常の配列からポインタへの減衰が原因です。

しかし、私は次の行がVS12に受け入れられるよう、それはconst char *可能性がどのように表示されていない。 char* s = "Hello";

これは通常の例外として、C++ 03(正しい行動でしたconst-correctnessのルール)、それ以来非難されています。 C++ 11準拠のコンパイラは、そのコードを受け入れるべきではありません。

+2

「通常のアレイからポインタへの減衰」は、すべてのコンテキストで発生するわけではありません。 Cでは、配列式が単項 '&'または 'sizeof'のオペランドでないか、配列(サブ)オブジェクトの初期化に使用される初期化子の文字列リテラルでない限り発生します。 C++にはより多くの例外があります。 –

+0

正しい用語は、_Array-to-pointer Conversion_です。これは、最新のC++標準の第4節で説明されている_Standard Conversion_です。大まかに言えば、標準的な変換は、特定のコンテキストでコンパイラによる式に暗黙的に適用される可能性があります。 –

5

文字列リテラルのタイプはchar const[N]です。ここで、Nは終端ヌル文字を含む文字数です。このタイプはではありません。char*に変換されますが、C++標準には、文字リテラルの割り当てをchar*に割り当てることができる節が含まれています。この句は、特にconstを持たないCコードの互換性をサポートするために追加されました。

規格におけるタイプに関連する句は、2.14.5 [lex.string]パラグラフ8:

通常の文字列リテラルと、UTF-8文字列リテラルとしても狭い文字列リテラルと呼ばれます。狭い文字列リテラルは "array of n const char"型を持ち、ここでnは以下に定義される文字列のサイズであり、静的記憶期間(3.7)を有する。

+1

この例外節は廃止予定です。文字列リテラルを 'char *'に代入しようとすると、コンパイル時にエラーが発生します。 – syam

+0

@syam - 「廃止予定」とはそれがまだ合法だが、将来はなくなる可能性があることを意味します。文字列リテラルの 'char *'への変換は、C++ 03では廃止されました。 C++ 11では無効になりました。ただし、言語定義には「コンパイル時エラー」は必要ありません。診断可能な制約に違反する場合、唯一の要件は、コンパイラーが診断を発行することです。コードをコンパイルし続けることは自由です。これは、実装固有の拡張のフックです。コンパイラがコードをコンパイルすることを拒否することを要求する唯一の状況があります: '#error'ディレクティブ。 –

-1

まずオフ、リテラルC++文字列のタイプは、Nconst charのアレイです。あなたがコードにあなたが持っている文字列リテラルではwchar_tを初期化したい場合は第二に、:

wchar_t* s = L"hello" 
+0

これは有効なコードではなく、指定されたエラーを確認するためのテストです。しかし、標準では本当に配列にする必要があります。 –

+7

いいえ、文字列リテラルは 'const char *'ではなく 'const char [SIZE]'です。 -1 – syam

+1

次に、 'sizeof" hello、world "が13を返す理由を説明してください。 –

関連する問題