栈区
里面存放的是临时变量等,自动申请,自动释放,不需程序员关心。
这里特别关注一下字符串:
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
char * getString()
{
char str[] = "Hello World!";
return str;
}
void test02()
{
char *s = NULL;
s = getString();
printf("s = %s\n",s);
}
int main()
{
test02();
return 0;
}
此时的输出结果是乱码,说明,这里的字符串存在栈区,在函数getString()结束之后就被释放了。
而如果换成是:char *str = (char *)"Hello World!";
则可以正确得到结果。说明此时的字符串存在全局区。
全局区
里面存放的是全局变量,常量等。
那么,有个问题了,一直模糊,今天记录一下答案。C语言中的常量包括:整型常量,实型常量,字符型常量(如’z’,'3’等),字符串常量(如"hjfgh"等),以及枚举型常量。因此,虽然上面的那个"Hello World"是字符型常量,但是不同的赋值方法,它存放的位置并不一样。好神奇(苦笑)。
关于全局区,有如下几个问题:
1、关于extern关键字
第一个代码在第一个cpp里面
extern int g_a = 10;//通过使用extern关键字,
//g_a的值在另一个cpp里面也可以用
这段代码在另一个cpp里面(同一项目的)
void test02()
{
//声明,告诉编译器符号存在.
extern int g_a;
printf("g_a = %d\n",g_a);
//这里最终可以打印出g_a的值为10;
}
int main()
{
test02();
return 0;
}
更神奇的是,在第一个cpp里面定义g_a时,如果不加extern,也可以输出10.就是说在定义变量时其实是默认extern的。但是!,在第二个cpp使用g_a之前,必须申明extern,不然不行。
2.关于 static关键字
static int b = 20;
//全局静态变量,内部链接 ,从定义到文件结尾。
这样在定义全局变量的时候就避免了像上面那样被外部extern.
另外,static用于局部变量,静态局部变量,即使在声明时未赋初值,编译器也会把它初始化为0。
堆区
这里就是我们程序员用malloc和new动态申请的空间的来源。我们知道malloc和new申请的空间不会自动释放,需要使用free和delete释放。
1.关于malloc函数的使用,
int * p = (int *)malloc(sizeof(int) *5);
//这句话表示申请5个int型的空间,并且返回值为第一个int型的地址的指针。
//这里,有几个问题明确一下。
//指针的值是地址。指针本身是一个数据类型,它的变量自然也有地址。
//来看一个例子
int main()
{
int i = 0;
int* p = &i; //也就是说p存放的是值是i的地址
int* t = p;
cout << &i << endl; //00DCF918(本次运行的地址)
cout << p << endl; //00DCF918
cout << &p << endl; //00DCF90C
cout << t << endl; //00DCF918
//从这里可以看到,t的值也是i的地址。
cout << &t << endl; //00DCF900
//即指针对指针赋值的 时候就相当于整型赋值
cout << *t << endl; //解引用是取t中存放的地址的对应数据。
return 0;
}
2.只要是连续的内存都可以使用下标来访问。
3.在使用完malloc申请的内存之后,需要做两件事:
free(p); //需要把它给释放了,不然会造成内存泄漏。
p = NULL; //要将p置空,不然会造成野指针。
4.下面这段代码是关于堆区的精髓展示
//用二级指针
void allocateSpace2(int **q/*out*/)
{
int *temp = (int *)malloc(sizeof(int) *5);
if(NULL == temp) //前面说过的数据有效性验证
{
return;
}
for(int i=0;i<5;i++)
{
temp[i] = 100 + i;
}
*q = temp;
}
void test02()
{
int *p = NULL; //p的值是0,p的地址是某一数值
allocateSpace2(&p); //这是取p的地址传参。
//因为上面函数定义的形参是int**,所以,是参数值为地址的地址。
//有因为上面函数的最后*q = temp; 这句话的意思其实是说p=temp.
//因为*q=p.因此,使用这个办法可以将数据真正的取到。
for(int i = 0;i<5;i++)
{
printf("%d ",p[i]);
}
printf("\n");
free(p);
p = NULL;
}
int main()
{
test02();
return 0;
}