不錯的文章,關於棧和地址
數據在內存中存儲,採用大小端模式,內IA-32平臺下,棧向下存儲,先申請空間的變量存於棧的高地址中,後申請的空間位於棧的末端(低地址)空間中,下面用一些示例來進行說明(以下示例在VC6.0環境下編譯和調試):
1,函數中的變量
函數中的變量,先申請的函數在內存的高地址,後申請的函數在內存的低地址,我們建立一個工程,控制檯應用程序,編寫如下代碼:
void main()
{
int i;
int j;
int k;
char c;
float f;
printf("i:%X\n",&i);
printf("j:%X\n",&j);
printf("k:%X\n",&k);
printf("c:%X\n",&c);
printf("f:%X\n",&f);
}
運行結果:
i:12FF7C
j:12FF78
k:12FF74
c:12FF70
f:12FF6C
可以知道,變量i的地址爲:0x0012ff7c
變量j的地址爲:0x0012ff78
變量k的地址爲:0x0012ff74
變量c的地址爲:0x0012ff70
變量f的地址爲:0x0012ff6c
我們在函數體中先定義的變量i,i的地址在這5個變量中是最高的,和變量j的地址值差4字節,首先,字節長度來看,i,j,k,f都是4字節長度,c爲1字節長度,在空間申請時,根據4字節做字節對齊,內存模型如下:
│……… 高地址 ………│
├────────────┤
│ 0x0012FF7F │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF7E │
├┄┄┄┄┄┄┄┄ i ┄┤
│ 0x0012FF7D │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF7C │ i的首地址:0x0012FF7C
├────────────┤
│ 0x0012FF7B │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF7A │
├┄┄┄┄┄┄┄┄ j ┄┤
│ 0x0012FF79 │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF78 │ j的首地址:0x0012FF78
├────────────┤
│ 0x0012FF77 │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF76 │
├┄┄┄┄┄┄┄┄ k ┄┤
│ 0x0012FF75 │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF74 │ k的首地址:0x0012FF74
├────────────┤
│ 0x0012FF73 null │
├────────────┤
│ 0x0012FF72 null │
├────────────┤
│ 0x0012FF71 null │
├────────────┤
│ 0x0012FF70 c │ c的首地址:0x0012FF70
├────────────┤
│ 0x0012FF6F │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF6E │
├┄┄┄┄┄┄┄┄ f ┄┤
│ 0x0012FF6D │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF6C │ f的首地址:0x0012FF6C
├────────────┤
│ │
│……… 低地址 ………│
2,複雜數據類型--數組
在數組中的數據存儲的模型與函數體中變量的存儲類似,但是存儲的方式相反,建立工程,編寫如下代碼,查看數組數據的地址:
void main()
{
char c=0;
int a[3]={0};
double d=0;
printf("%x\n",&c);
printf("%x\n",&a[0]);
printf("%x\n",&a[1]);
printf("%x\n",&a[2]);
printf("%x\n",&d);
}
運行結果如下:
c:12ff7c
a[0]:12ff70
a[1]:12ff74
a[2]:12ff78
d:12ff68
可以知道,變量c的地址:0x0012FF7C
數組元素a[0]的地址:0x0012FF70
數組元素a[1]的地址:0x0012FF74
數組元素a[2]的地址:0x0012FF78
變量d的地址:0x0012FF68
數組元素在內存中根據數組的大小申請空間,然後根據數組中的元素進行空間的分配,數組的最後一個元素存儲在高地址,數組的第一個元素存儲在低地址,內存模型如下:
│……… 高地址 ………│
├────────────┤
│ 0x0012FF7F null │
├────────────┤
│ 0x0012FF7E null │
├────────────┤
│ 0x0012FF7D null │
├────────────┤
│ 0x0012FF7C c │ c的首地址:0x0012FF7C
├────────────┤─────────────────────┐
│ 0x0012FF7B │ │
├┄┄┄┄┄┄┄┄ ┄┤ │
│ 0x0012FF7A │ │
├┄┄┄┄┄┄┄┄ a[2] ┄┤ │
│ 0x0012FF79 │ │
├┄┄┄┄┄┄┄┄ ┄┤ │
│ 0x0012FF78 │ a[2]的首地址:0x0012FF78 │
├────────────┤ │
│ 0x0012FF77 │ │
├┄┄┄┄┄┄┄┄ ┄┤ │
│ 0x0012FF76 │ 數組a[3] 的內存空間
├┄┄┄┄┄┄┄┄ a[1] ┄┤ │
│ 0x0012FF75 │ │
├┄┄┄┄┄┄┄┄ ┄┤ │
│ 0x0012FF74 │ a[1]的首地址:0x0012FF74 │
├────────────┤ │
│ 0x0012FF73 │ │
├┄┄┄┄┄┄┄┄ ┄┤ │
│ 0x0012FF72 │ │
├┄┄┄┄┄┄┄┄ a[0] ┄┤ │
│ 0x0012FF71 │ │
├┄┄┄┄┄┄┄┄ ┄┤ │
│ 0x0012FF70 │ a[0]的首地址:0x0012FF70 │
├────────────┤─────────────────────┘
│ 0x0012FF6F │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF6E │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF6D │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF6C │
├┄┄┄┄┄┄┄┄ d ┄┤
│ 0x0012FF6B │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF6A │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF69 │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF68 │ d的首地址:0x0012FF68
├────────────┤
│ │
│……… 低地址 ………│
3,複雜數據類型--結構體
結構體在內存中的存儲方式和函數體相反,與數組類似,結構體內最後定義的數據存儲在高地址中,按下面的代碼進行驗證:
typedef struct SS
{
int i;
char a;
short s[3];
int b;
}SS;
void main()
{
int i=0;
SS s={0};
int j=0;
printf("i:%x\n",&i);
printf("s:%x\n",&s);
printf("s.i:%x\n",&s.i);
printf("s.a:%x\n",&s.a);
printf("s.s[0]:%x\n",&s.s[0]);
printf("s.s[1]:%x\n",&s.s[1]);
printf("s.s[2]:%x\n",&s.s[2]);
printf("s.b:%x\n",&s.b);
printf("j:%x\n",&j);
}
運行結果如下:
i:12ff7c
s:12ff6c
s.i:12ff6c
s.a:12ff70
s.s[0]:12ff72
s.s[1]:12ff74
s.s[2]:12ff76
s.b:12ff78
j:12ff68
可以知道,變量i的地址:0x0012FF7C
結構體s的首地址:0x0012FF6C
結構體s的變量i的地址:0x0012FF6C
結構體s的變量a的地址:0x0012FF70
結構體s的變量s[0]的地址:0x0012FF72
結構體s的變量s[1]的地址:0x0012FF74
結構體s的變量s[2]的地址:0x0012FF76
結構體s的變量s.b的地址:0x0012FF78
變量j的地址:0x0012FF68
內存模型如下:
│……… 高地址 ………│
├────────────┤
│ 0x0012FF7F │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF7E │
├┄┄┄┄┄┄┄┄ i ┄┤
│ 0x0012FF7D │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF7C │ i的首地址:0x0012FF7C
├────────────┤────────────────────┐
│ 0x0012FF7B │ │
├┄┄┄┄┄┄┄┄ ┄┤ │
│ 0x0012FF7A │ │
├┄┄┄┄┄┄┄┄ s.b ┄┤ │
│ 0x0012FF79 │ │
├┄┄┄┄┄┄┄┄ ┄┤ │
│ 0x0012FF78 │ s.b的首地址:0x0012FF78 │
├────────────┤ │
│ 0x0012FF77 │ │
├┄┄┄┄┄┄┄┄s.s[2]┄┤ │
│ 0x0012FF76 │ s.s[2]的首地址:0x0012FF76 │
├────────────┤ │
│ 0x0012FF75 │ │
├┄┄┄┄┄┄┄┄s.s[1]┄┤ │
│ 0x0012FF74 │ s.s[1]的首地址:0x0012FF74 │
├────────────┤ │
│ 0x0012FF73 │ 結構體s的內存空間分配
├┄┄┄┄┄┄┄┄s.s[0]┄┤ │
│ 0x0012FF72 │ s.s[0]的首地址:0x0012FF72 │
├────────────┤ │
│ 0x0012FF71 null │ │
├────────────┤ │
│ 0x0012FF70 s.a │ s.a的首地址:0x0012FF70 │
├────────────┤ │
│ 0x0012FF6F │ │
├┄┄┄┄┄┄┄┄ ┄┤ │
│ 0x0012FF6E │ │
├┄┄┄┄┄┄┄┄ s.i ┄┤ │
│ 0x0012FF6D │ │
├┄┄┄┄┄┄┄┄ ┄┤ │
│ 0x0012FF6C │ 結構體s(s.i)的首地址:0x0012FF6C │
├────────────┤────────────────────┘
│ 0x0012FF6B │
├┄┄┄┄┄┄┄┄ ┄┤
│ 0x0012FF6A │
├┄┄┄┄┄┄┄┄ d ┄┤
│ 0x0012FF69 │
├┄┄┄┄┄┄┄┄ ┄┤
│