关于内存分区的笔记

栈区

里面存放的是临时变量等,自动申请,自动释放,不需程序员关心。
这里特别关注一下字符串:

#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;
}
发布了27 篇原创文章 · 获赞 0 · 访问量 428

猜你喜欢

转载自blog.csdn.net/weixin_40007143/article/details/103706057