Cの文字列リテラルのタイプは何ですか?それは...ですか char *
またはconst char *
またはconst char * const
?
C++はどうですか?
Cでは、文字列リテラルのタイプはchar[]
です-タイプによってはconst
ではありませんが、内容を変更することは未定義の動作です。また、同じ内容(または十分な量の同じ内容)を持つ2つの異なる文字列リテラルは、同じ配列要素を共有する場合と共有しない場合があります。
C99標準6.4.5/5「文字列リテラル-セマンティクス」から:
変換フェーズ7では、1つまたは複数の文字列リテラルから生成される各マルチバイト文字シーケンスに、値0のバイトまたはコードが追加されます。次に、マルチバイト文字シーケンスを使用して、シーケンスを含めるのに十分な静的ストレージ期間と長さの配列を初期化します。文字列リテラルの場合、配列要素のタイプは
char
であり、マルチバイト文字シーケンスの個々のバイトで初期化されます。ワイド文字列リテラルの場合、配列要素のタイプはwchar_t
で、ワイド文字のシーケンスで初期化されます...要素が適切な値を持っている場合、これらの配列が異なるかどうかは不定です。プログラムがこのような配列を変更しようとした場合の動作は未定義です。
C++では、「通常の文字列リテラルの型は 'nの配列const char
'」です(2.13.4/1 "文字列リテラル"から)。ただし、C++標準には、文字列リテラルへのポインターを非const修飾ポインターに簡単に変換する特別なケースがあります(4.2/2 "配列からポインターへの変換")。
ワイド文字列リテラルではない文字列リテラル(2.13.4)は、「pointer to char」型の右辺値に変換できます。ワイド文字列リテラルは、「wchar_tへのポインター」型の右辺値に変換できます。
補足として-C/C++の配列はポインタにすぐに変換されるため、C/C++の配列と同様に、文字列リテラルをポインタコンテキストで使用できます。
追加の編集:以下は、文字列リテラル型に関してCおよびC++標準が行った選択の根拠についての私の側の実際の推測のほとんどです。だから、一粒の塩でそれを取る(しかし、修正や追加の詳細がある場合はコメントしてください):
C標準では、文字列リテラルを非const型にすることを選択したと思います。リテラルを指す非const修飾されたchar
ポインターを使用できると期待するコードが多かったためです。 const
修飾子が追加されたとき(私が間違っていなかった場合、ANSI標準化の前後に行われましたが、K&R Cが大量の既存のコードを蓄積してからずっと後)、文字列リテラルのみへのポインターを作成した場合キャストなしでchar const*
タイプに割り当てることができるため、存在するほぼすべてのプログラムを変更する必要がありました。標準を承認する良い方法ではありません...
文字列リテラルがconst
修飾されているというC++への変更は、主にリテラル文字列が "char const*
"引数を取るオーバーロードとより適切に一致できるようにするために行われたと思います。認識された型システムの穴を閉じたいという要望もあったと思いますが、配列からポインターへの変換の特殊なケースによって、穴は大きく開放されました。
標準の附属書Dは、「文字列リテラルのconst修飾から非const修飾への暗黙的な変換(4.2)は推奨されない」ことを示していますが、コンパイラーの実装者や標準委員会は実際にプラグを抜く用意があります(他の巧妙な手法を考案できる場合を除きますが、穴は元に戻ります)。
C文字列リテラルの型はchar [n]
ここで、n
は文字数+ 1に等しく、文字列の末尾の暗黙的なゼロを考慮します。
配列は静的に割り当てられます。 const
ではありませんが、変更は未定義の動作です。
ポインタ型char *
または不完全なタイプchar []
、sizeof
は期待どおりに動作しませんでした。
文字列リテラルの作成const
はC++のイディオムであり、C標準の一部ではありません。
さまざまな歴史的理由により、Cでは文字列リテラルは常にchar[]
型でした。
初期(C90)では、文字列リテラルを変更すると、未定義の動作が発生することが述べられていました。
彼らはそのような変更を禁止しませんでしたし、文字列リテラルconst char[]
も作成しませんでした。これは、古いコードとの下位互換性のためです。一部の古いOS(特にDOS)は、文字列リテラルを変更しても抗議しなかったため、そのようなコードがたくさんありました。
Cには、最新のC標準でさえ、今日でもこの欠陥があります。
C++はCから同じ非常に同じ欠陥を継承しましたが、後のC++標準では、最終的に文字列リテラルconst
を作成しました(C++ 03では廃止され、最後にC++ 11で修正されました)。
以前はchar[]
タイプでした。現在、タイプはconst char[]
です。