0

私は非常に単純な C プログラムを持っており、ローカル変数の割り当てに使用されているメモリ アドレスを (自分の好奇心から) 調査しています。私のプログラムは次のとおりです。

#include <stdio.h>

int main()
{
  char buffer_1[8], buffer_2[8], buffer_3[8];
  printf("address of buffer_1 %p\n", buffer_1);
  printf("address of buffer_2 %p\n", buffer_2);
  printf("address of buffer_3 %p\n", buffer_3);
  return 0;
}

出力は次のとおりです。

address of buffer_1 0x7fff5fbfec30
address of buffer_2 0x7fff5fbfec20
address of buffer_3 0x7fff5fbfec10

私の質問は、アドレスが小さくなっているように見えるのはなぜですか? これには何らかの論理がありますか?ありがとうございました。

4

4 に答える 4

1

コンパイラーは、自動変数を使ってやりたいことを何でもすることができます。この場合、それらをスタックに連続して配置しているように見えます。現在使用されている最も一般的なシステムでは、スタックは下向きに成長します。

于 2012-08-06T05:27:16.790 に答える
1

C プログラムの出力は、プラットフォームやコンパイラに依存します。アドレスの配置は、システムがリトル エンディアンかビッグ エンディアンかによって異なるため、完璧な答えは 1 つだけではありません。コンパイルしている OS の種類。コンパイルするメモリ アーキテクチャの種類。使用しているコンパイラの種類 (およびコンパイラにもバグがある可能性があります) プラットフォームが 64 ビットか 32 ビットか。などなど。

しかし、何よりも重要なのは、プロセッサ アーキテクチャの種類です。:)

プロセッサごとのスタック成長戦略のリストを次に示します。

x86,PDP11    Downwards
System z     In a linked list fashion, downwards, mostly.
ARM          Select-able and can grow in either up or downward.
Mostek6502   Downwards (but only 256 bytes).
SPARC        In a circular fashion with a sliding window, a limited depth stack. 
RCA1802A     Subject to SCRT(Standard Call and Return Technique) implementation.

ただし、一般に、コンパイラはコンパイル時に、これらのアドレスを生成されたバイナリ ファイルにマップする必要があります。次に、実行時に、バイナリ ファイルがメモリ アドレスの連続したセットを占有する (または占有するふりをする) 場合があります。あなたの場合、C ソースによって出力されたアドレスは、スタックが下向きに成長していることを示しています。

于 2012-08-06T06:24:39.540 に答える
1

ほとんどのコンパイラは、関数の最初の段階で、ローカル変数にスタック メモリを 1 ステップで割り当てます。メモリは、1 つの連続したブロックとして割り当てられます。これらの状況下では、コンパイラは明らかに、そのブロック内のローカル変数に対して完全に任意のメモリ レイアウトを自由に使用できます。宣言した順にアドレスが増えるように配置できれば。または減少します。またはランダムに配置します。実装の詳細です。そして、その背後にあるロジックはあまりありません。

あなたの場合、コンパイラが配列のメモリがスタックに順番に独立して割り当てられたように「ふり」を試みた可能性は十分にあります(そうではありませんでしたが)。プラットフォーム スタックが下向きに成長する場合 (多くのプラットフォームでそうであるように)、後で宣言されたオブジェクトのアドレスが小さくなることが予想されます。

ただし、関数はローカル オブジェクトを個別に割り当てません。その上、この言語はローカル オブジェクト アドレス間の関係を保証しません。したがって、一方の順序を他方より優先する本当の理由はありません。

于 2012-08-06T05:36:58.977 に答える
0

基本的に、コンパイラはすべての変数にメモリを割り当てる責任があります。配列はスタック上のアドレスを取得します。しかし、あなたが得ているo/pとは何の関係もありません。基本的には、コンパイラがその時点で連続したスペース(またはメモリのチャンク)が空であることを発見したため、プログラムに割り当てられました。

于 2012-08-06T07:21:23.150 に答える