-3

コンピューターのメモリに格納されている c 変数が、格納され
ている場所と格納されているデータ構造形式をどのように説明しているのか、少し混乱しています。

 #include<stdio.h>
 #include<conio.h>
 int main(void)
 {
  int r;
  int a,b,c;
  a=10;
  b=20;
   c=30;
 char e=3;
 int f[10]={1,2,3};

  printf("the value of pointers is\n %d\n %d\n %d\n %d\n %d\n %d\n",&a,&b,&c,&e,&f,&r);
  getch();
 }
4

3 に答える 3

1

一般に (つまり、ここに書くすべての文に対して誰かが反例を見つけることができるため)、定義できるすべての C 変数はメモリ (RAM) に格納されます。さまざまなタイプの変数を、さまざまなタイプ (セグメント) のメモリに保存できます。

コンパイルされた C プログラムは、コード セグメントにあります。関数で定義する通常の変数は、プログラムのスタック(メモリも) で定義されます。malloc() などで割り当てる変数。ヒープ上に配置されます(これもメモリです)。ファイルに書き込まない限り、ディスクには何も保存されません。

さて、私の言ったことは正しいでしょうか?ではない正確に。OS は、ページングメカニズムを使用して、RAM に保存するものとディスクに保存するものを決定しています。メモリはページ単位で管理されます。OSがそうすべきだと判断した場合、各ページはハードドライブにスワップアウトできるため、すべての変数をそのページに配置できます。つまり、それらはディスクに保存されます。このメモリが後で必要になる場合、OS はこのページをメモリにスワップインします。

繰り返しますが、これは一般的なことです。OS でページングを無効にすることができます。その場合、すべてが常にメモリ内に保存されます。また、メモリの一部をディスク ドライブとして表示するようにマップすることもできます。この場合、このディスクに書き込まれたすべてのデータがメモリに残ります。

等々...

于 2012-10-11T20:17:18.563 に答える
1

にはさまざまなストレージ クラスがありc、例のものはスタックに格納されています。

おそらく最初に読んだほうがいいでしょうc

于 2012-10-11T18:14:03.363 に答える
0

変数が格納される場所と方法の正確な詳細は、実装次第です。言語定義は、変数の可視性と有効期間のみを指定し、変数が格納されるメカニズムは指定しません。

Red Hat 7.2 上の gcc 2.96 という特定の実装を見ていきます。

簡単なソース ファイルを次に示します。

#include <stdio.h>

int gvar = 1;            // file scope, static extent

int main(void)
{
  static int svar = 2;  // block scope, static keyword => static extent
  int avar = 3;         // block scope, auto extent

  do {
    int avar2 = 4;      // block scope, auto extent
    printf("gvar   = %d (%p)\nsvar   = %d (%p)\navar   = %d (%p)\navar2  = %d (%p)\n", 
    gvar, (void *) &gvar,
    svar, (void *) &svar,
    avar, (void *) &avar,
    avar2, (void *) &avar2);
  } while (0);

  return 0;
}

キーワードstaticまたはファイル スコープ (関数の外部) で宣言された変数には、記憶域クラスがstaticあります。つまり、これらの変数のメモリは、プログラムの起動時に割り当てられ、プログラムが終了するまで保持されます。staticブロック内でキーワードなしで宣言された変数にはストレージ クラスがあります。つまり、変数はautoそのブロック内にのみ存在しますavar2ループの外で名前で参照することはできずdo、ループの終了後にその値を保持することは保証されていません。

プログラムをコンパイルします

gcc -o storage -g storage.c -ansi -pedantic -Wall -Werror -Wa,-aldh=storage.lst.redhat

-Wa,-alhd=...、生成されたマシン コードのリストを指定されたファイルに書き込みます。デバッグ フラグを追加したため-g、元の C ソースがマシン コードにインターリーブされます。

プログラムからの出力は次のとおりです。

gvar = 1 (0x80495b0)
svar = 2 (0x80495b4)
avar = 3 (0xbfffe4e4)
avar2 = 4 (0xbfffe4e0)

gvar明らかに、この実装では、およびのような静的エクステントを持つ変数は、およびavarのような自動エクステントを持つ変数とはまったく異なる場所に格納されます。 avarx

生成されたアセンブリ コードのリストを次に示します (一部の改ページを除く)。

   1 .ファイル「storage.c」
   2 .バージョン「01.01」
   5 .テキスト
   6 .Ltext0:
 165 .globl gvar
 166 .データ
 168 .アライン 4
 171 グヴァル:
 172 0000 01000000 .ロング 1
 173 .アライン 4
 176 svar.0:
 177 0004 02000000 .long 2
 178 .セクション .rodata
 179 .アライン 32
 180 .LC0:
 181 0000 67766172 .string "gvar = %d (%p)\nsvar = %d (%p)\nvar = %d (%p)\navar2 = %d (%p)\n"
 181 2020203D
 181 20256420
 181 28257029
 181 0A737661
 182 0044 00000000 .テキスト
 182 00000000
 182 00000000
 182 00000000
 182 00000000
 183 .アライン 4
 185 .グローバルメイン
 187 メイン:
   1:storage.c **** #インクルード
   2:storage.c ****
   3:storage.c **** int gvar = 1;
   4:storage.c****
   5:storage.c **** int main(void)
   6:storage.c **** {
 189 .LM1:
 190 .LBB2:
 191 0000 55 プシュル %ebp
 192 0001 89E5 movl %esp, %ebp
 193 0003 83EC08 subl $8、%esp
   7:storage.c **** static int svar = 2;
   8:storage.c **** int avar = 3;
 195 .LM2:
 196 0006 C745FC03 移動 $3, -4(%ebp)
 196 000000
   9:storage.c****
  10:storage.c **** ド {
  11:storage.c **** int avar2 = 4;
 198 .LM3:
 199 .LBB3:
 200 000d C745F804 移動 $4, -8(%ebp)
 200 000000
  12:storage.c **** printf("gvar = %d (%p)\nsvar = %d (%p)\nvar = %d (%p)\navar2 = %d (%p)\n" 、
 202 .LM4:
 203 0014 83EC0C subl $12、%esp
 204 0017 8D45F8 leal -8(%ebp), %eax
 205 001a 50 プシュル %eax
 206 001b FF75F8 プッシュル -8(%ebp)
 207 001e 8D45FC leal -4(%ebp), %eax
 208 0021 50 プシュル %eax
 209 0022 FF75FC プッシュ -4(%ebp)
 210 0025 68040000 プッシュル $svar.0
 210 00
 211 002a FF350400 pushl svar.0
 211 0000
 212 0030 68000000 プッシュル $gvar
 212 00
 213 0035 FF350000 pushl gvar
 213 0000
 214 003b 68000000 プッシュ $.LC0
 214 00
 215 0040 E8FCFFFF call printf
 215FF
 216 0045 83C430 追加 $48、%esp
  13:storage.c **** gvar, (void *) &gvar,
  14:storage.c **** svar, (void *) &svar,
  15:storage.c **** avar, (void *) &avar,
  16:storage.c **** avar2, (void *) &avar2);
  17:storage.c **** } while (0);
 218 .LM5:
 219 .LBE3:
  18:storage.c****
  19:storage.c **** リターン 0;
 221 .LM6:
 222 0048 B8000000 movl $0, %eax
 222 00
  20:ストレージ.c****}
 224 .LM7:
 225 .LBE2:
 226 004d C9 休暇
 227 004e C3 ret
 228 .Lfe1:
 237 .Lscope0:
 239.テキスト
 241 .Letext:
 242 004f 90 .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.2)"

苦労することはたくさんありますが、メモリ アドレスにこのような違いが生じる理由がわかります。

台詞

   5 .テキスト
   6 .Ltext0:
 165 .globl gvar
 166 .データ
 168 .アライン 4
 171 グヴァル:
 172 0000 01000000 .ロング 1
 173 .アライン 4
 176 svar.0:
 177 0004 02000000 .long 2

gvarとのメモリは、プログラム コードが存在するプログラム イメージ svarのセクションにあることを教えてください。.text

線を比較すると

195 .LM2:
 196 0006 C745FC03 移動 $3, -4(%ebp)
 196 000000
...
 198 .LM3:
 199 .LBB3:
 200 000d C745F804 移動 $4, -8(%ebp)
 200 000000

avarとのメモリavar2が現在のフレーム ポインタ ( に格納されている) を基準に配置されていることを教えてください%ebpavarはフレーム ポインタから 4 バイト オフセットで格納され、avar2はフレーム ポインタから 8 バイト オフセットで格納されます。

繰り返しになりますが、これは、1 つのオペレーティング システム上の 1 つのコンパイラの 1 つのバージョンで行う方法です。異なるオペレーティング システム上の異なるコンパイラは、異なる構造を使用する場合があります (ただし、このアプローチは非常に一般的です)。

正確な詳細を知りたくてうずうずしている場合は、アーキテクチャ (x86 対 Power 対 MIPS 対 ...) についてさらに学びたいと思うでしょう。また、アセンブリ プログラミングを実行したいと思うでしょう。


1. これは、ブロックに出入りするたびにメモリが割り当てられ、割り当てが解除されることを必ずしも意味しないことに注意してください。通常、同じメモリ位置が再利用されますが、ブロックが終了したときと同じ値を持つことは保証できません。

于 2012-10-11T20:04:17.333 に答える