1

さて、私は main() 自動ローカル変数がスタックに保存され、関数の自動ローカル変数も保存されていることを知っていますが、gcc バージョン 4.6.3 で次のコードを試したとき:

#include <stdio.h>

    int main(int argc, char *argv[]) {

        int var1;
        int var2;
        int var3;
        int var4;
        printf("%p\n%p\n%p\n%p\n",&var1,&var2,&var3,&var4);
        }

結果は次のとおりです。

0xbfca41e0
0xbfca41e4
0xbfca41e8
0xbfca41ec

結果によると、スタックの上部に var4 があり、スタックの下部に var1 があり、スタック ポインターは現在 var1 アドレスの下のアドレスを指しています....しかし、スタックの上部に var4 があり、下部に var1 があるのはなぜですか。 .. var1 の後に宣言されているので、論理的には、var1 はスタックの一番上にある必要があり、var1 の後に宣言された変数はメモリ内でその下にある必要があると思います...したがって、私の例では次のようになります。

>>var1  at 0xbfca41ec
>>var2  at 0xbfca41e8
>>var3  at 0xbfca41e4
>>var4  at 0xbfca41e0
>>and stack pointer pointing here  
..

..

編集1:

@AusCBloke のコメントを読んだ後、次のコードを試しました。

#include <stdio.h>


 void fun(){
 int var1;
 int var2;
 printf("inside the function\n");
 printf("%p\n%p\n",&var1,&var2);

 }


 int main(int argc, char *argv[]) {


int var1;
int var2;
int var3;
int var4;



printf("inside the main\n");
printf("%p\n%p\n%p\n%p\n",&var1,&var2,&var3,&var4);
fun();
return 0;
}

そして結果:

inside the main
0xbfe82d60
0xbfe82d64
0xbfe82d68
0xbfe82d6c
inside the function
0xbfe82d28
0xbfe82d2c

したがって、fun() スタック フレーム内の変数は main() スタック フレーム内の変数の下にあり、これはスタックの性質によると当てはまりますが、同じスタック フレーム内では上から下に並べる必要はありません。

ありがとう@AusCBloke .....あなたのコメントは私を大いに助けてくれました

4

5 に答える 5

8

これらの変数は、宣言された順序で割り当てる必要はありません。それらはコンパイラーによって移動されたり、完全に最適化されたりすることさえあります。相対アドレスを同じままにする必要がある場合は、struct.

于 2012-07-16T22:15:51.590 に答える
2

通常、自動保存期間を持つオブジェクトはスタックに保存されますが、言語標準では必要ありません。実際、標準(リンクは最新のプレリリース C11 ドラフトへのリンク) では、「スタック」という言葉さえ言及されていません。

残念ながら、「スタック」という言葉はあいまいです。

最も抽象的な意味では、スタックは、最近追加されたアイテムが最初に削除されるデータ構造です (後入れ先出し、または LIFO)。static自動保存期間を持つオブジェクト (つまり、キーワードなしで関数内で定義されたオブジェクト) の有効期間に関する要件は、ある種のスタックのような割り当てを意味します。

「スタック」という言葉は、通常、最上位の要素を指す「スタック ポインター」によって制御される連続したメモリ領域を指すためにも使用されます。スタックは、スタック ポインターをベースから遠ざけると大きくなり、ベースに近づけると縮小します。ほとんどの C コンパイラは、この種の連続スタックを使用して自動オブジェクトを実装しますが、すべてがそうしているわけではありません。ヒープのような構造から関数呼び出し用のストレージを割り当てる IBM メインフレーム システム用の C コンパイラがあり、ネストされた呼び出しのアドレスは昇順または降順で一様である必要はありません。

これは珍しい実装であり、このアプローチが一般的に使用されないのには十分な理由があります (連続したスタックはより単純で効率的であり、通常は CPU によってサポートされます)。ただし、C 標準は、特定のスキームを必要としないように慎重に作成されており、移植できるように慎重に作成された C コードは、コンパイラがどの方法を選択しても正しく動作します。知る必要はありません。のアドレスについて本当に知っておく必要があるのvar1は、それが であるということだけ&var1です。と書くif (&var1 < &var2) { ... }と、おそらく何か間違ったことをしている可能性があります(その式の動作は未定義です、BTW)。

それが標準的なCの答えです。あなたの質問にはというタグが付けられています。私の知る限り、gcc のすべてのバージョンは連続したスタックを使用しています。しかし、そうであっても、これを利用するメリットはほとんどありません。

于 2012-07-16T23:17:25.953 に答える
1

多くの (ほとんどの) 最新のプラットフォームでは、スタックはメモリ内の上位アドレスから下位アドレスに成長します。つまり プログラムを開始すると、スタック ポインターはすぐにメモリ内のアドレスに配置されます。このアドレスは、プログラムの最大スタック サイズによって決まります。物事がスタックにプッシュされると、スタックポインターは実際に下に移動ます。

于 2012-07-16T23:33:47.677 に答える
0

99.9999% の確率で答えはイエスです。また、スタックは Intel アーキテクチャ マシンでは上向きではなく下向きに成長します。下の領域は、スタックの仮想の「トップ」になります (いわば上下逆です)。

したがって、技術的には、変数スタック メモリ内で正しい順序になっています。

編集:ただし、これはおそらくまだコンパイラ固有です。

于 2012-07-16T22:16:09.627 に答える
0

私は間違っている可能性がありますが、スタックは下位メモリ アドレスから開始され、その後追加されます。したがって、var4 が一番上にあるのは正しいことです。やっぱりスタックです!

編集: その背後にあるアセンブリ コードには、メモリ スタックの一番下にスタック ポインターがあり、データが追加されるたびにスタック ポインターがインクリメントされ、次の変数が一番上に置かれます。

于 2012-07-16T22:11:58.370 に答える