在c语言中主要把内存分为5个区,如下图所示:
先来看一段代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * getStr1()
{
char *p1 = "abcdefg2";
return p1;
}
char * getStr2()
{
char *p2 = "abcdefg22";
return p2;
}
int main(int argc,char *argv[])
{
char *p1 = NULL;
char *p2 = NULL;
p1 = getStr1();
p2 = getStr2();
//打印p1,p2所指向内存空间的数据
printf("p1:%s,p2:%s\n", p1, p2);
//打印p1,p2的值
printf("p1:%d,p2:%d\n", p1, p2);
system("pause");
return 0;
}
打印结果如图所示。两个指针存储的地址不同
如果将两个函数所指向的字符串相同的话,即都指向"abcdefg2"的话,打印结果就会发生改变。
两个指针所存储的地址都相同 。
这是为什么呢?
运行完第一个程序的内存指向如图所示,由于字符串常量都是放在常量区的,所以由于两个字符串不同即分配的地址也不相同。
第二个程序由于两个字符串相同,所以编译器认为两个一致的字符串的地址一致,所以传到主函数的地址也是一致的,也就出现p1和p2存储的值相同。
再来看看堆和栈在编译器中是怎么体现的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//堆
char *getMem(int num)
{
char *p1 = NULL;
p1 = (char *)malloc(sizeof(char)*num);
if (p1 == NULL)
{
return NULL;
}
return p1;
}
//栈
char *getMem2()
{
char buf[64] = { 0 };
strcpy(buf, "123456789");
return buf;
}
int main(int argc, char *argv[])
{
char *tmp = NULL;
tmp = getMem(10);
if (tmp == NULL)
{
return -1;
}
strcpy(tmp, "1111222");//向tmp所指向的内存空间中copy数据
printf("heap:getMem:%s\n", tmp);
tmp = getMem2();
printf("stack:getMem:%s\n", tmp);
system("pause");
return 0;
}
打印结果如图所示
getMem函数是从堆上获取地址
getMem2函数是从栈上获取地址,由于栈在函数运行结束后就会自动析构该函数开辟在栈上的内存,即buf数组在执行完getMem2函数后就在内存中消失了,所以这时候将他的地址返回出去就会出现打印出来的内存是乱码的。