0

重複の可能性:
Cの関数からローカル変数を返す

これについて考えれば考えるほど、なぜこれがそれほど良い考えではないのか確信が持てなくなります...コンパイラは、関数内からの自動変数が呼び出し元に戻ることについて不平を言います。例えば:

char * foo() {
   char bar[11];
   fgets(bar, 10, stdin);
   return bar;
}

対:

char bar[11];
char * foo() {
   fgets(bar, 10, stdin);
   return bar;
}

私はおそらくあまり意味がありません。内部にポインタ宣言があるという問題を完全には理解していません。呼び出し元は単にメモリアドレスを想定しているだけではないでしょうか。

4

3 に答える 3

1

最初の例では、配列barは関数に対してローカルであるため、関数が戻ったときに配列は存在しなくなります。したがって、結果として得られるポインタは、以前は指していたものがもう存在しないため、有用なものを指す可能性は低くなります。

于 2012-07-09T21:41:12.523 に答える
0

最初の例は完全に間違っています。メモリスペースを作成し、関数内に書き込んでポインタを返すため、存在しないメモリセグメントへのポインタを返します。このメモリは、機能から戻った後に解放されます。2番目の例は正しいですが、可能であればグローバル変数の使用は避けてください。

編集:ポインタを関数に戻した後、関数の外部でメモリを使用できるようにする場合は、動的メモリ割り当てを使用します(calloc関数を確認してください)。

于 2012-07-09T21:41:27.770 に答える
0

bar、すべての意図と目的のために、関数が戻ると存在しなくなります。自動ストレージ期間が割り当てられ、後でそのメモリから読み取ろうとすると、未定義の動作が発生します。スタックが通常使用されるので、関数が戻った後、そのデータを有効な状態に保つことをどのように想像しますか?

代わりにchar*、関数への入力として、それが参照するメモリブロックのサイズとともに、呼び出し元のバッファを埋めることができます。つまり、次のようになります。

void foo(char *buf, buf_size) {
   fgets(buf, buf_size, stdin);
}

これはCでは非常に一般的で慣用的なものです。何fgetsが行われているのかを見てください。呼び出し元であるあなたに、埋めるためのバッファーを提供するように求めています。これにより、関数から返されたメモリの割り当てを解除する責任者についての混乱を避けることができます(関数が動的に割り当てられたメモリへのポインタを返した場合は文書化する必要があります)。

ところで、文字をfgets読み取りnum-1、nullが終了するので、バッファのサイズを渡すだけで、size-1現在行っているように渡す必要はありません。

于 2012-07-09T21:41:35.273 に答える