malloc函数
头文件
#include <stdlib.h>或#include<malloc.h>
函数原型
void *malloc(unsigned int size)
作用
在内存的动态存储区中分配一个长度为size的连续空间。此函数的返回值是分配区域的起始地址,或者说,此函数是一个指针型函数,返回的指针指向该分配域的开头位置。
返回值
在以前malloc返回的是char型指针,新的ANSIC标准规定,该函数返回为void型指针。
void* 表示未确定类型1的指针。C,C++规定,void* 类型可以通过类型转换强制转换为任何其它类型的指针,因此必要时要进行强制类型转换。
例如:
char *str = (char *) malloc(15);//定义一个指向char(空间大小为15个字节)的指针
如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定),否则返回空指针NULL。
释放
当内存不再使用时,应使用free()函数将内存块释放。
malloc与new的区别
1、返回值
new 返回指定类型的指针,并且可以自动计算所需要大小。比如:
int *p;
p=new int; //返回类型为int\* 类型(整数型指针),分配大小为 sizeof(int);
或:
int* p;
p=new int [100]; //返回类型为 int* 类型(整数型指针),分配大小为 sizeof(int) * 100;
而 malloc 则必须由我们计算要字节数,并且在返回后强行转换为实际类型的指针。
int* p;
p = (int *) malloc (sizeof(int));
简单来说,new我们只需要考虑元素(结点)个数,而malloc还需要考虑到每个元素(结点)所占空间大小,即sizeof(…)。
2、初始化
malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。
而new可以在分配内存后添加初值列表进行初始化。
接下来拓展一下——
new函数的初始化
在默认情况下,new是不会对分配的int进行初始化的。要想使分配的int初始化为0,需要显式地调用其初始化函数:
int* buffer = new int(); // 分配的一个int初始化为0
int* buffer = new int(0); // 分配的一个int初始化为0
int* buffer = new int[100];//分配的一个100个int,均为随机值
int* buffer = new int[100](); // 分配的512个int都初始化为0
对于单个int,也可以初始化为非0值:
int* buffer = new int(5); // 分配的一个int初始化为5
但是无法将分配的所有元素(如数组全体元素)同时初始化为非0值,以下代码是不合法的:
int* buffer = new int[512](0); // 语法错误!
int* buffer = new int[512](5); // 语法错误!
言归正传,接着不同点来
3、释放函数
new函数用delete函数进行释放,而malloc函数用free()函数进行释放。
除了分配的方法及最后释放的方法不一样以外,通过malloc或new得到指针,在其它操作上保持一致。
注:
使用malloc分配的内存空间在虚拟地址空间上是连续的,即外部使用起来是连续的,可以对指针进行运算而且结果正确。但是转换到物理内存空间上有可能是不连续的,因为有可能相邻的两个字节是在不同的物理分页上;(关于这部分的详细解释可以参考堆分配的内存空间(malloc/new)是否连续,本人也在学习中)
继续来到realloc:
realloc函数
函数原型
extern void *realloc(void *mem_address, unsigned int newsize)
头文件
#include <stdlib.h> 或#include <malloc.h>
作用
先判断当前的指针是否有足够的连续空间,如果有,改变mem_address指向的地址,并且将返回mem_address;如果空间不够,先按照newsize指定的大小分配另一块新空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放2,不需要使用free),同时返回新分配的内存区域的首地址。(尽量按照自己的理解翻译了一下百度百科)
新的大小可大可小(如果新的大小大于原内存大小,则新分配部分不会被初始化;如果新的大小小于原内存大小,可能会导致数据丢失。(这句话摘自百度百科,我实际操作中并没有理解…)
举例说明:
int *p=(int *)malloc(sizeof(int));//定义一个指向int的指针,指针名为p
int *base=(int *)realloc(p,10);//重新将p指向的地址扩大范围为10个字节,用新指针base指向扩大后的地址,同时自动释放原指针p;
malloc与realloc搭配使用,用法也有很多相似之处。
附上一段关于一些使用realloc的总结,该段总结转自他人。
链接:https://blog.csdn.net/dcx1205/article/details/24316773
- realloc失败的时候,返回NULL。
- realloc失败的时候,原来的内存不改变,不会释放也不会移动。
- 假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址; 假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被自动 free 掉,realloc返回新内存的地址。
- 如果size为0,效果等同于 free ()。这里需要注意的是只对 指针 本身进行释放,例如对二维指针**a,对a调用realloc时只会释放一维,使用时谨防 内存泄露 。
- 传递给realloc的 指针 必须是先前通过 malloc (), calloc (), 或realloc()分配的。
6.传递给realloc的 指针 可以为空,等同于 malloc 。
写在最后的一些疑惑:
放图
第一,这里的指针p仍然存在,不是网上有的地方说的“野指针”;
第二,在我缩小了内存块后,还可以连续的输出,这里我查阅了部分资料,看不懂QAQ;
希望大佬能用通俗易懂的方式释疑!