3

これら3つの違いを理解するのに苦労しています。

const char * f() {
  return "this is a test";
}

const char * g() {
  const char * str = "test again";
  return str;
}

const double * h() {
  const double a = 2.718;
  return &a;
}

として、の警告が表示h()されwarning: address of local variable ‘a’ returnedます。gcc -Wallこれは理にかなっていますが、コンパイラ( )がf()andg()関数で問題ない理由がわかりません。

  • そこにローカル変数はありませんか?
  • いつ、どのようにポインタが返されるf()g()、割り当てが解除されますか?
4

7 に答える 7

8

文字列リテラルはローカルスタックフレームに格納されません。それらは実行可能ファイルの固定された場所にあります。対比:

const char * g() {
  const char * p = "test again";
  return p;
}

const char * g() {
  const char a[] = "test again";
  return a;
}

前者の場合、戻り値は実行可能ファイル内の固定された場所を指します。後者の場合、戻り値はスタック(現在は無効な場所)を指します。

于 2012-08-29T18:10:59.273 に答える
6

文字列リテラルです。

n3337 2.14.5 / 8

通常の文字列リテラルおよびUTF-8文字列リテラルは、ナロー文字列リテラルとも呼ばれます。狭い文字列リテラルの型は「arrayofnconst char」です。ここで、nは以下に定義する文字列のサイズであり、 静的な保存期間があります。

于 2012-08-29T18:09:26.923 に答える
3
const char * g() {
  const char * str = "test again";
  return str;
}

これはローカル変数のアドレスを返しません。変数はstrあるため、アドレスはそれ自体とは異なるもの&strにする必要があります。str

std::cout << (void*) str  << std::endl; 
std::cout << (void*) &str << std::endl; //address of str (local variable)

彼らは異なる値を印刷するでしょう!

したがって、より適切な例は次のようになります。

const char ** g() {
  const char * str = "test again";
  return &str;  //difference!
}

これで、ローカル変数のアドレスが返されます。優れたコンパイラ、これに対して警告を発する場合があります。

別の例はこれです:

const char * g() {
  const char str[] = "test again"; //difference!
  return str;  //same as before
}

strこれで、ローカル変数のアドレスではないように見えるものを返しても、この場合のように、strとの値は&strまったく同じになるという警告が表示される場合があります。今すぐこれらを印刷してみてください:

std::cout << (void*) str  << std::endl; 
std::cout << (void*) &str << std::endl; //address of str (local variable)

彼らは同じ値を印刷します!

于 2012-08-29T18:12:20.463 に答える
1

関数h内のaは、関数が戻った後には存在しないローカル変数です。その変数へのポインターを返しているので、関数の外部でポインターを逆参照することは正しくなく、未定義の動作です。

fで、リテラルg文字列を返します。リテラル文字列には静的ストレージがあります。スタックには割り当てられ、関数の有効期間を超えて存在します。

の定義ではg

const char *g()
{
   const char *str = "test again";
   return str;
}

str ローカル変数ですが、ローカル(静的に割り当てられたメモリ)へのポインタです。ローカル変数への参照ではなく、返されるのはそのアドレスです。

の別の定義を考えてみましょうg

const char *g()
{
    const char str[] = "test again";
    // incorrect: can't use str after the return:
    return str;
}

gこれで、関数と同じ問題が発生します。コンパイルhすると、ローカル変数のアドレスを返すことについて同じ警告が表示されます。

于 2012-08-29T18:09:58.993 に答える
1

文字列リテラルはローカル変数ではありません。3番目の関数に相当する文字列はこれです

const char * f() {
  const char str[] = "this is a test";
  return str;
}
于 2012-08-29T18:10:55.153 に答える
0

文字列リテラルのストレージ割り当ては静的であるため、警告は表示されません。

これを試してみると、未定義の動作が発生します。

const char* getFoo()
{

  std::string foo("hi");
  return foo.c_str();
}

文字列fooがリテラル文字列のコピーを作成したためです。

于 2012-08-29T18:09:55.647 に答える
0

これらの文字列は物理的かつ永続的にデータメモリ内に配置されるため、アドレスは永続的です。自動変数はスタック上にあるため、呼び出しから戻った瞬間に消えます。

于 2012-08-29T18:44:21.683 に答える