一.静态内存分配和动态内存分配
静态内存分配:静态内存分配的空间都是固定的大小,且分配的是栈区的空间,函数执行结束时这些存储单元自动被释放。
动态内存分配:在程序执行的过程中动态地分配或回收存储空间。动态内存分配的是堆上的内存,堆上分配的内存不会主动释放,需由程序员自己释放或是在程序结束时还给操作系统。
内存区域分区
栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但分配的内存容量有限。栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。
堆区(heap):一般由程序员自己分配释放,若程序员不释放,程序结束时可能由OS回收。
静态段(静态区)(static):存放全局变量、静态数据/程序结束后由系统释放。
代码段:存放函数体(类成员函数和全局函数)的二进制代码。
二.动态内存分配函数
在使用动态内存分配函数时,需引用对应头文件(#include )
1.malloc
void* malloc(size_t size);
函数的功能:向内存申请一块连续可用的空间,并返回指向这块空间的指针。
若开辟成功,则返回一个指向开辟好空间的指针;若开辟失败,则返回一个NULL指针(因此一定要对malloc函数的返回值进行检查)
函数的返回值类型为void*,所以malloc函数并不知道开辟空间的类型,由使用者在使用的时候决定
若参数size为0,此时malloc的行为是标准未定义的,取决于编译器。
#include<stdlib.h>#include<stdio.h>intmain() { int*p= (int*)malloc(40); //对返回值进行检查if (p==NULL) { perror("malloc"); return1; } for (inti=0; i<10; i++) { printf("%d\n", *(p+i)); } //释放动态开辟的内存free(p); p=NULL; return0; }
malloc函数不会对空间进行初始化,因此存放内容为随机值
2.free
void free(void* ptr)
free函数是用来释放动态开辟的内存的。
若参数ptr指向的空间不是动态开辟的,那么free函数的行为是未定义的
若ptr是NULL指针,那么函数什么事都不做
注:在释放动态开辟的内存后,应将ptr置为NULL,因为ptr指针指向的动态开辟的空间已经被释放了后,若ptr仍指向那块空间,后面若使用了ptr访问指向的空间,则非法访问该内存。
3.calloc
void* calloc(size_t num, size_t size)
函数的功能:为num个大小为size的元素开辟一块内存空间,并且把空间的每个字节初始化为0.
calloc函数与malloc函数的区别只在于calloc函数会在返回地址之前将申请的空间的每个字节全部初始化为0
#include<stdlib.h>#include<stdio.h>intmain() { int*p= (int*)calloc(10, 4); //对返回值进行检查if (p==NULL) { perror("calloc"); return1; } for (inti=0; i<10; i++) { printf("%d\n", *(p+i)); } //释放动态开辟的内存free(p); p=NULL; return0; }
calloc函数会将空间的每个字节初始化为0
4.realloc
void* realloc(void* ptr ,size_t size)
realloc函数的功能:
若申请的空间过小或是过大,则可用realloc函数对内存大小进行调整。
ptr:要调整的内存地址
size:要调整之后的大小
在增加空间时,若原本开辟的内存后面有足够的空间,则直接在后面开辟新的空间;
若后面的空间不够,则realloc会先开辟新的空间,并将旧空间中的数据拷贝到新的空间中,拷贝后则释放旧的空间,最后返回新空间的起始地址。
若开辟失败,则返回NULL,因此应先对返回值进行判断,防止原始数据丢失
#include<stdlib.h>#include<stdio.h>intmain() { int*p= (int*)calloc(10, 4); //对返回值进行检查if (p==NULL) { perror("calloc"); return1; } int*ptr= (int*)realloc(p, 20*sizeof(int)); //判断ptr是否为NULLif (ptr!=NULL) { p=ptr; ptr=NULL; } else { perror("realloc"); return1; } for (inti=0; i<20; i++) { printf("%d\n", *(p+i)); } //释放动态开辟的内存free(p); p=NULL; return0; }
realloc函数也不会对新开辟的空间进行初始化