ページ 11

関数内の自動変数(ポインタと配列の違い)

Posted: 2014年5月12日(月) 22:29
by テニス
すみません!先ほど質問した者ですが、肝心なことを聞く前に「解決」をしてしまったため、読んで貰えなかったら
困るのでもう一度トピック建てさせて下さい。

コード:

void charTest(char** str){
    char *p = "charTest";      //これはOK
    //char p[]="charTest";       //これはNG
    
    *str = p;
}

int _tmain(int argc, _TCHAR* argv[])
{
    char* cMoji = "main";

    charTest(&cMoji);
    std::cout << cMoji << "\n";

    return 0;
}
先ほど教えていただいた部分を修正したコードです。

charTest内で、
char*のポインタ型で自動変数を作成すると、main関数での出力は「charTest」と表示されますが、
char型の配列で自動変数を作成すると、main関数での出力は 不定のランダムな文字列 が表示されます。

関数を抜けたら、自動変数はメモリから削除されるので、不定な文字列が表示されるのが
当然かなと思ったのですが、なぜポインタ変数は関数を抜けても残っているのでしょうか?

Re: 関数内の自動変数(ポインタと配列の違い)

Posted: 2014年5月12日(月) 22:41
by みけCAT
(staticでない)「ポインタ変数」は関数(スコープ)を抜けたら残りません。
「文字列リテラル」はstatic領域に確保される(?)ので残るのだと思います。

Re: 関数内の自動変数(ポインタと配列の違い)

Posted: 2014年5月12日(月) 23:07
by h2so5
"charTest" 自体は静的記憶領域に存在します。
ですから、自動変数pの寿命と関係なくプログラム実行中ずっと有効です。

char *p = "charTest"; の場合はpは "charTest" のアドレスを指しているので関数を抜けても問題ありません。

しかし、char p[] = "charTest"; は配列 p の内容を "charTest" で初期化するという意味です。
pは "charTest" ではなく配列を指していますから、関数を抜けて配列の寿命がなくなると無効なアドレスになってしまいます。

Re: 関数内の自動変数(ポインタと配列の違い)

Posted: 2014年5月12日(月) 23:21
by テニス
みけCATさんh2so5さんありがとうございます!
ばっちり理解出来ました!

char* p = "charTest"は、静的領域にある文字列リテラルのアドレスを渡しており、関数を抜けても有効で、
char p[] = "charTest"は、関数内で自動変数を初期化しただけなので、関数を抜けたら消滅するんですね。

今日一日だけですごくポインタの理解が深まりました。
ありがたいサイトに感謝です。