-1
#include<stdio.h>

void bar()
{
 int a=4;
}
void foo()
{
 int a;
 printf("%d",a);
}
int main()
{
 bar();
 foo(); 
}

上記のプログラムは、出力を何らかのジャンク値として提供していると確信しています(これは、コンパイルして実行したときに起こることです)。しかし、一部のコンパイラが出力を 4 自体として与える可能性があるという記事を読みました。与えられた説明は、それがアクティベーション スタックとアクティベーション フレームに関連しているというものでした。理解できない。bar() 関数の int a=4 の値が、後で使用するためにアクティベーション スタックのどこかに格納されているようなものですか??混乱しています!!

4

4 に答える 4

3

一部のコンパイラが何をするかについて心配する必要はありません。それは「未定義の動作」と呼ばれます。常に、変数を希望どおりに初期化するようにしてください。

繰り返しになりますが、論理がないため「理解しよう」とすることは無意味であり、「予期される動作」ではないことは確かです。ただし、関数がインライン化されている場合、一部のコンパイラが cpu でレジスタを再利用する可能性があるため、そうなる可能性があります。あなたの関数の後に誰かが関数を実行して「あなたの値を盗む」ことを何らかの形で心配している場合は、関数を終了する前にゼロに設定してください。しかし、それは「ベストプラクティス」ではありません。

つまり、2 番目の関数が a の代わりに 'b' を使用したとしても、メモリ空間を再利用している場合は 4 が含まれる可能性があります。または、他のコンパイラが実際にアルファベット順に事前割り当てする可能性があるため、「a」のみが機能します。繰り返しますが、これは未定義の動作です。

于 2013-10-23T18:31:58.993 に答える
1

関数fooは初期化されていない変数を使用しています。コンパイラは、この状況で好きなことを自由に行うことができます。実際には、以前にスタックに配置された変数を、現在は機能していないフレームで取得する場合があります。あなたが言うように、それは 4 かもしれませんが、代わりに他の何かかもしれません。この種の動作に頼らないでください... 99% 信頼できるかもしれませんが、100 回の試行でうまくいかない可能性があります。

于 2013-10-23T18:33:47.597 に答える
1

明確にするために、foo の a がそこに設定されたバーで 4 になる可能性があります (同じ名前の BTW とは関係ありません)。ただし、これはコンパイラ マシンなどに大きく依存します。

(foo で) 実際に行っていることは「未定義の動作」です。値を指定せずに a を使用します。未定義とは、コンパイラが何かを実行したり、ハードドライブをフォーマットしたり、親友の誕生日を含むランダムな値を出力したり、4 を出力したりする可能性があることを意味します。

多くのシステムでスタック フレームが構築される方法では、bar がアドレスに 4 を書き込み、foo がそれを読み戻すため、なぜ 4 になるのでしょうか。2 つの関数のパラメーター、戻り値の型、およびローカルの数は同じであるため、最初のローカルが同じメモリ位置に割り当てられる可能性があります。これが、それらが同じ値を持つ可能性があると読んだ理由ですが、これは意図的なものではなく偶然によるものです

ところで、あなたは4を得たかどうか、おそらくそうではありません

于 2013-10-23T18:40:35.530 に答える