質問
文字列リテラルが関数の外部で定義されていないのではないかと恐れているため、文字列リテラルを返すことを常に避けようとしています。しかし、これが事実かどうかはわかりません。たとえば、次の関数を見てみましょう。
const char *
return_a_string(void)
{
return "blah";
}
これは正しいコードですか?それは私のために動作しますが、多分それは私のコンパイラ(gcc)でのみ動作します。したがって、問題は、do(string)リテラルにスコープがあるか、常に存在/定義されているかです。
解決
このコードはすべてのプラットフォームで問題ありません。文字列は、静的な文字列リテラルとしてバイナリにコンパイルされます。たとえば、Windowsを使用している場合は、メモ帳で.exeを開き、文字列自体を検索することもできます。
静的な文字列リテラルスコープであるため、問題ではありません。
文字列プーリング:
注意すべきことの1つは、場合によっては、同一の文字列リテラルを「プール」できることです。実行可能ファイルのスペースを節約します。この場合、同じ文字列リテラルは同じメモリアドレスを持つことができます。ただし、そうなるとは限りません。
ほとんどのコンパイラでは、攪拌リテラルに静的文字列プーリングを使用するかどうかを設定できます。
文字列リテラルの最大サイズ:
いくつかのコンパイラには、文字列リテラルの最大サイズがあります。たとえば、VC ++の場合、これは約2,048バイトです。
文字列リテラルを変更すると、未定義の動作が発生します:
文字列リテラルの変更は行わないでください。未定義の動作があります。
char * sz = "this is a test";
sz[0] = 'T'; //<--- undefined results
広い文字列リテラル:
上記のすべては、ワイド文字列リテラルに等しく適用されます。
例:L&quot;これはワイド文字列リテラルです&quot ;;
C ++標準の状態:(セクションlex.string)
1文字列リテラルはシーケンスです 文字の lex.ccon )二重引用符で囲まれ、オプションで始まる &quot; ...&quot;のような文字LまたはL&quot; ...&quot;。始まらない文字列リテラル Lは通常の文字列リテラルで、ナローとも呼ばれます 文字列リテラル。通常の文字列リテラルの型は&quot; array of n const char&quot;静的ストレージ期間( basic.stc )、ここでnは サイズ 以下で定義される文字列の、指定された 文字。 L&quot; asdf&quot;など、Lで始まる文字列リテラル、 は ワイド文字列リテラル。ワイド文字列リテラルの型は&quot; array of n const wchar_t&quot;静的な保存期間があります。nはサイズです の 以下で定義される文字列。指定された文字で初期化されます。 ters。
2すべての文字列リテラルが異なる(つまり、 重複しないオブジェクト)は実装定義です。の効果 の 文字列リテラルを変更しようとすることは未定義です。
他のヒント
混乱をある程度明確にするために例を挙げます
char *f()
{
char a[]="SUMIT";
return a;
}
これは機能しません。
しかし
char *f()
{
char *a="SUMIT";
return a;
}
これは動作します。
理由:&quot; SUMIT&quot;グローバルスコープを持つリテラルです。 一方、文字のシーケンスである配列{'S'、 'U'、 'M'、 'I'、&quot; T '' \ 0 '} 範囲が限定されており、プログラムが返されるとすぐに消えます。
これが役立つことを願って
これは、他の人が説明したように、C(またはC ++)で有効です。
注意が必要なことの1つは、dllを使用している場合、このコードを含むdllがアンロードされるとポインターが有効にならないことです。
C(またはC ++)標準は、実行時のコードのロードとアンロードを理解または考慮していないため、実装定義の結果に直面することはありません。この場合、結果は文字列リテラルです。静的な保存期間を持つことになっていますが、呼び出しコードのPOVから、プログラムの全期間にわたって持続しないように見えます。
はい、大丈夫です。それらはグローバル文字列テーブルに存在します。
いいえ、文字列リテラルにはスコープがないため、コードはすべてのプラットフォームとコンパイラーで機能することが保証されています。これらはプログラムのバイナリイメージに保存されるため、いつでもアクセスできます。ただし、( const
をキャストして)それらに書き込もうとすると、未定義の動作が発生します。
実際には、プログラムのロード時にロードされる実行可能ファイルのデータセクションに格納されているゼロで終わる文字列へのポインタを返します。文字を変更しようとしないでください。予測できない結果が生じる可能性があります...
ブライアンが言及した未定義の結果に注意することは本当に重要です。 const char *型を返すように関数を宣言しているので問題ありませんが、多くのプラットフォームでは、文字列リテラルは実行可能ファイルの読み取り専用セグメント(通常はテキストセグメント)に配置され、それらを変更するとアクセス違反が発生しますほとんどのプラットフォームで。