先从一个例子说起
#include "stdafx.h"
#include <stdio.h>
#include <stdio.h>
const int i = 1;
char s[] = "hello";
int d[]={2,3,7,13,15};
char *q = "asdfsd";
int main(int argc, char* argv[])
{
char * p = "hello";
const int j = 1;
static int l = 1;
int k = 1;
printf("i=%d/n", &i);
printf("s=%d/n", s);
printf("d=%d/n", d);
printf("q=%d/n", q);
printf("p=%d/n", p);
printf("j=%d/n", &j);
printf("k=%d/n", &k);
printf("l=%d/n", &l);
printf("hi=%d/n", &"hi");
return 0;
}
程序输出:
可以根据地址顺序对其进行分类,得出红色部分的结论,这里按地址排序。
//
栈:函数内部变量、常量
k=1245044
j= 1245048
//
代码数据区(常量区):全局常量、全局或者内部常指针字符串以及代码中各字符串常量
q=4349980
i= 4349988 (大家注意这个i
)
hi=4350004
p=4350072 //与“hi”相差68,是因为程序内部控制字符串”*=%d/n等占用了空间
//
静态存储区:全局变量,函数内部静态变量
s=4361552
d=4361560
l= 4361584
再看看另一个例子:
const int i = 1;
int main(int argc, char* argv[])
{
const int j = 1;;
int *p;
p =(int *)&j;
*p = 100;
printf("j=%d, *p=%d/n", j, *p);
p =(int *)&i;
*p = 99;
printf("i=%d, *p=%d/n", i, *p);
return 0;
}
大家可以先猜猜程序运行结果
解释:根据开始的结论,可以知道j分配在栈空间,可以修改。i分配在代码数据区,受系统保护,不允许修改
所以程序首先输出 j=1, *p=100, 之后在试图修改i值的时候导致崩溃
另外:函数输出 j=1是因为j是常量,所以编译起直接用1对其进行了替换,见汇编代码:
0040103E mov edx,dword ptr [ebp-8]
00401041 mov eax,dword ptr [edx]
00401043 push eax //*p根据地址读取
00401044 push 1 //j 直接使用1
00401046 push offset string "j=%d, *a=%d/n" (00420fdc)
0040104B call printf (00401130)
附:根据windows内存管理机制,全局常量、全局或者内部常指针字符串以及代码中各字符串常量以及代码都分配在不可写的4k页面上,受系统保护,且是进程间共享的