0

次のコードを見てください。

char* test ( )
{
    char word[20];
    printf ("Type a word: ");
    scanf ("%s", word);
    return word;
}

void main()
{
    printf("%s",test());
}

関数が戻ると、変数wordは破棄され、ガベージ値が出力されます。でも交換したら

char word[20];

char *word;

正しい値を出力します。私によると、ポインター変数は文字配列と同様に破棄され、出力はガベージ値になるはずです。誰も曖昧さを説明できますか?

4

4 に答える 4

5

未定義の振る舞いはまさにそれです-未定義。時々それはうまくいくように見えるでしょう、しかしそれはただの偶然です。この場合、初期化されていないポインタがたまたま有効な書き込み可能メモリを指している可能性があり、そのメモリは他の目的に使用されていないため、値の書き込みと読み取りに成功しました。これは明らかにあなたが信頼すべきものではありません。

于 2012-06-24T15:04:23.320 に答える
2

どちらの方法でも未定義の動作がありますが、純粋に「ここで何が起こっているのか」という観点から見ると、2 つの間にはまだいくつかの違いがあります。

配列を使用すると、配列が保持するデータがスタックに割り当てられます。関数が戻ると、そのメモリはスタックの一部ではなくなり、呼び出しの過程でほぼ確実上書きされますprintf

ポインターを使用すると、ポインターがたまたま指していたランダムな場所にデータが書き込まれます。そこに書くことは未定義の動作ですが、単純な統計によると、(たとえば) ~40 億の場所の 32 ビット アドレス空間がある場合、新しいいくつかの命令で上書きされる可能性はかなり低いです。

明らかにどちらも実行すべきではありません、得られた結果も特に驚くべきものではありません。

于 2012-06-24T15:10:01.260 に答える
0

mainプログラムの最初の実行中に、プロセス メモリのスタック セグメントに関数のアクティベーション レコードが作成されます。そのmainアクティベーション レコードでは、その function( ) のローカル変数にメモリを割り当てmain、内部目的のためにさらにメモリを割り当てます。プログラムにはローカル変数がないため、アクティベーション レコードmain内のローカル変数にメモリを割り当てません。main

次に、 function を呼び出すためのステートメントの実行中testに、呼び出し元の function( ) のアクティベーション レコードをもう 1 つ作成し、ローカル変数にバイトをtest割り当てます。20word

コントロールが関数testを終了すると、その関数用に作成されたアクティベーション レコードがそのスタックからポップされます。printf次に、呼び出された関数の残りのステートメント () を実行し続けますmain。ここで printf は、testすでにスタックからポップされている関数のローカル変数の文字を出力しようとしています。したがって、この動作は未定義です。適切な文字列が出力される場合もあれば、不要な文字列が出力される場合もあります。

したがって、この状況では、動的メモリのみが明らかになります。動的メモリの助けを借りて、変数の有効期間 (またはスコープ) を制御できます。したがって、以下のように動的メモリを使用します。

char *word = NULL:
word = (char *) malloc(sizeof(char) * 20);

注 : malloc の戻り値の NULL チェックに注意しprintf、main 関数の後で割り当てられたメモリを解放することを忘れないでください。

于 2012-06-24T18:34:08.050 に答える
0

char 配列は関数内で定義および宣言されているため、ローカル変数であり、関数が戻ると存在しなくなります。char ポインターを使用してALLOCATE MEMORY FOR ITを使用すると、それは残り、必要なのはポインター (別名、数値) だけです。

int main(int argc, char* argv[]) {
    printf("%s", test());
    return 0;
}

char* test(void) {
    char* str = (char*)malloc(20 * sizeof(char));
    scanf("%19s", str);
    return str;
}

%s の代わりに %19s を使用したことに注目してください。現在の関数では、ユーザーが 20 文字以上入力すると、簡単にバッファ オーバーフローが発生する可能性があります。

于 2012-06-24T15:10:55.453 に答える