第一:内存分配的主要区域

主要区域: 1. 栈区(stack) 2. 堆区(heap) 3. 常量区 4. 静态区(static) 5. 代码区(code)

第二: 栈区(stack)

	存放内容:
			存放函数内的局部变量,形参和函数返回值以及返回地址等。
	特点:
			1. 编译器自动分配和释放,不需要开发人员来维护;
			2. 存的数据,只要出了其作用域,系统自动对其内容进行回收;
			3. 由操作系统来管理;
			4. 先进后出的原则(First In Last Out, FILO)
			5. 向下增长,先创建的局部变量的地址 高于 后创建的局部变量的地址
	例子:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	int a = 0;
	int b = 0;
	int c[] = { 1,2,3,4,5 };
	printf("a addr: %p\n\n\n", &a);
	printf("b addr: %p\n\n\n", &b);
	printf("c addr: %p\n", c);
	return 0;
}

第三:堆区(heap)

	存放内容:
			有malloc、calloc、realloc动态内存函数开辟的内存空间。
	特点:
			1. 需要手动释放内存:free()函数;如果不释放发生内存泄露的风险;
			2. 如果不手动释放,当程序结束时,可能有OS回收;
			3. 自下向上,即先申请的内存空间的地址 低于 后申请的内存空间地址;

例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	int* p1 = (int*)malloc(4 * sizeof(int)); // 用malloc申请4个整型空间
	int* p2 = (int*)calloc(4, sizeof(int)); // 用calloc申请4个整型空间
	int* p3 = (int*)realloc(NULL,4 * sizeof(int)); // 用realloc申请4个整型空间
	if (NULL != p1)
	{
		printf("第一次申请空间的地址: %p\n\n\n\n", p1);
		free(p1);
		p1 = NULL;
	}
	if (NULL != p2)
	{
		printf("第二次申请空间的地址: %p\n\n\n\n", p2);
		free(p2);
		p2 = NULL;
	}
	if (NULL != p3)
	{
		printf("第三次申请空间的地址: %p\n\n\n\n", p3);
		free(p3);
		p3 = NULL;
	}
	return 0;
}

第四: 静态区(static)

	存放内容:
			存放全局变量,静态变量(static修饰的变量)
	特点:
			程序结束后,由系统释放。
			对于静态的局部变量,只会初始化一次,如果多次初始化,则多余的初始化无效。
			自下向上模式,即先存放到低地址,在存放到高地址。

例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int a1 = 1;
int a2 = 1;
static int b = 2;
void test()
{
	static c = 1;
	c++;
	printf("c = %d and addr: %p\n\n", c, &c);
}
int main()
{
	int i;
	printf("a1 addr: %p\n\n", &a1);
	printf("a2 addr: %p\n\n", &a2);
	printf("b  addr: %p\n\n", &b);
	for (i = 0; i < 5; i++) { test(); }
	return 0;
}

第五:常量区

	存放内容:
			存放的是常量变量
	特点:
			该常量只能读,不能修改。

第六:代码区(code)

	存放内容:
			程序中的函数编译后cpu指令、存放函数体(包括结构体等)的二进制代码
	特点:
			1. 由系统来控制内存空间
			2. 只能读。