2

この例では、両方の文字列「jesus」が等しい(同じメモリ位置)ようです。

printf("%p\n","jesus");
printf("%p\n","jesus");

また、次の点にも注意してください。

printf("%p\n",&"jesus");
printf("%p\n","jesus");

同じように印刷しますが、次のようになります。

char* ptrToString = "jesus";
char* ptrToString = &"jesus"; //ERROR

だから私は割り当てられていない文字列がどのようにメモリに保存され、それを指す方法を知りたいです...

4

2 に答える 2

6

まず、なぜ同じ"jesus"&"jesus"あるか:"jesus"は型の配列でありconst char[6]、最初の要素へのポインタに減衰します。配列のアドレスを取得すると、型が。である配列へのポインタがconst char (*)[6]得られます。ただし、配列へのポインターは、最初の要素へのポインターと数値的に同じです(タイプのみが異なります)。

これは、最後の行にエラーがある理由も説明しています-タイプタイプが間違っています。必要なもの:

 const char (*pj)[6] = &"jesus";

最後に、問題は、繰り返される文字列リテラルが同じアドレスを持っているかどうかです。これは完全にコンパイラ次第です。非常に単純な場合は、ソースコードに文字列リテラルが出現するたびに個別のコピーを保存できます。少し賢い場合は、文字列リテラルごとに1つの一意のコピーのみを保存します。もちろん、文字列リテラルはメモリのどこかに、通常はプログラムイメージの読み取り専用データセグメントに格納されます。それらを静的に初期化されたグローバル変数と考えてください。

もう1つ、元のコードは実際には未定義の動作です。これは、引数を%p期待しているためであり、またはではありません。したがって、正しいコードは次のとおりです。void *const char *const char (*)[6]

printf("%p\n%p\n", (void const *)"jesus", (void const *)&"jesus");
于 2012-05-12T18:01:18.623 に答える
1

Cは慎重に指定された言語であり、いくつかの質問に答える可能性のある例について多くの観察を行うことができます。

  1. 文字リテラルは、初期化されたデータとしてメモリに保存されます。タイプがありarray of charます。
  2. バイトは。で埋め込むことができるため、必ずしも文字列である必要はありません。nul\0
  3. 同一の文字列リテラルが一意である必要はありませんが、プログラムがそれを変更しようとした場合に何が起こるかは未定義です。これにより、実装が適切と考えるように、それらを効果的に区別または「インターン」することができます。
  4. その最後の行を機能させるには、次のものが必要です。

    char (*ptrToString)[] = &"jesus"; // now not an ERROR

于 2012-05-12T18:12:53.080 に答える