内存区域管理

主要内容:内存区域管理

一、 C中内存区域划分
 在C语言中存储区一般分为:堆、栈、全局区(静态区)、常量区 。首先我们明确一些定义:
1、全局变量:定义在函数外部的变量称为全局变量;
2、局部变量:定义在函数内部的变量称为局部变量;(要注意的是:主函数也是函数,如果在主函数里面定义 int a ,则a是局部变量)。
3、Static:表静态,可以用static修饰变量或者函数;static修饰全局变量称为静态全局变量;static修饰全局变量局部称为静态局部变量;(全局变量,加了static修饰符后不管在哪里都存放在全局区(静态区),在所有函数体外定义的static变量表示在该文件中有效,不能extern到别的文件用,在函数体内定义的static表示只在该函数体内有效。)。
4、栈:由编译器自动分配释放。是用户存放程序临时创建的局部变量。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
5、堆:用malloc, calloc, realloc等分配内存的函数分配得到的就是在堆上。

他们所存放 的数据具体如下图:

内存区域管理_第1张图片

6、明确了各种变量在内存中中的存储后,我们来看几个例子:

#include 
 
int a=123; // a在全局(静态)变量区 (已初始化数据区 )
 
char *p1; // p1在全局(静态)变量区 (未初始化全局变量) 
 
int main()
{
	int b; //  b为局部变量,在栈区 
 
	char s[]="abc";   //s为局部数组变量,在栈区 
			          //"abc"为字符串常量,代码段
 
	char *p1,*p2; // p1,p2为局部变量,在栈区 
 
	char *p3="123456"; // p3在栈区,"123456"在代码段
 
	static int c=456; //c为静态局部变量,存储在全局(静态)变量区 (已初始化全局变量) 
 
    p1=(char*)malloc(10); //分配得来的10个字节的区域在堆区 
 
	p2=(char*)malloc(20); //分配得来的20个字节的区域在堆区 
 
	free(p1);
 
	free(p2);
 
	p1=NULL; //显示地将p1置为NULL,避免以后错误地使用p1
 
	p2=NULL;
}

二、 内存中的变量的生命周期、作用域、默认值、链接属性、内存区域

 具体展示如下表:

内存 生命周期 作用域 默认值 链接属性 内存区域
普通全局变量 程序运行开始创建、程序结束才销毁 从定义到本文件结束 0 外部 全局变量区
静态全局变量 程序运行开始创建、程序结束才销毁;不能extern到别的文件使用 从定义到本文件结束 0 内部 全局变量区
普通局部变量 进入函数时创建、函数结束才销毁 本函数内部有效 随机值
静态局部变量 进入函数时创建、程序结束才销毁 本函数内部有效 0 静态变量区
动态内存 通过调用动态内存函数创建、free销毁 随机值
普通函数 无、一直存在 外部 代码段
静态函数 无、一直存在 内部 代码段

内部/外部概念明确:主要存在于多文件系统中:

extern int g_d;  //引入外部符号,如果函数或者变量用static修饰,不允许其他文件引用

三、 例子理解

1、在主函数之前可以运行其他函数吗?(如下结果证明可以)

int g_a;           // 普通全局变量
static int g_b;   //静态全局变量

class A
{
public:
	A()
	{
		printf("A 我来了\n");
	}
	~A()
	{
		printf("A 我走了\n");
	}
};

int main()
{
	printf("main 我来了\n");
	int a = 0;//局部变量
	printf("main 我走了\n");
	return 0;
}

内存区域管理_第2张图片

2、普通和静态全局变量用法
内存区域管理_第3张图片

//全局变量
int g_a = 0;
int g_b;

void Fun()
{
	printf("%d\n",g_a);
}

extern int g_d;   //extern为引用外部的变量,这个文件的定义存在于
                   上图“temp.h”文件中,可以被外部文件引用。
//extern int g_e;  //int g_e用static修饰,无法引用,出错。

int main()
{
	printf("%d\n",g_a);//全局变量g_a作用域为整个文件,所以为0;
	printf("%d\n",g_b); //结果为0,说明全局变量如果没有初始化,默认值为0;
	printf("%d\n",g_d); //引用“temp.h”文件中g_d,值为20;
	//printf("%d\n",g_e);  //无法引用

	g_a = 10;
	Fun();     //局部变量g_a ,带入fun()函数中,值为10。
	return 0;
}

内存区域管理_第4张图片

内存区域管理_第5张图片

3、普通局部变量(进入函数时创建,函数结束才销毁,本函数内部有效)

void Fun()
{
	int a = 0;    //局部变量a,每次结束fun()函数后,值销毁。因此每次只打印1.
	a++;
	printf("%d\n",a);
}

int main()
{
	for(int i=0;i<10;i++)
	{
		Fun();
	}
	return 0;
}

内存区域管理_第6张图片

4、静态局部变量(进入函数时创建,程序结束才销毁)

void Fun()
{
	static int a = 0;
	a++;
	printf("%d\n",a);    //每次函数结束值不销毁,保留,直接下次用。
}

int main()
{
	for(int i=0;i<10;i++)
	{
		Fun();
	}
	return 0;
}

内存区域管理_第7张图片

你可能感兴趣的:(内存区域管理)