C库函数-malloc与realloc详解(含对new初始化介绍)

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

  1. realloc失败的时候,返回NULL。
  2. realloc失败的时候,原来的内存不改变,不会释放也不会移动。
  3. 假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址; 假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被自动 free 掉,realloc返回新内存的地址。
  4. 如果size为0,效果等同于 free ()。这里需要注意的是只对 指针 本身进行释放,例如对二维指针**a,对a调用realloc时只会释放一维,使用时谨防 内存泄露 。
  5. 传递给realloc的 指针 必须是先前通过 malloc (), calloc (), 或realloc()分配的。
    6.传递给realloc的 指针 可以为空,等同于 malloc 。

写在最后的一些疑惑:
放图
很好的说明了我的疑惑
第一,这里的指针p仍然存在,不是网上有的地方说的“野指针”;
第二,在我缩小了内存块后,还可以连续的输出,这里我查阅了部分资料,看不懂QAQ;

希望大佬能用通俗易懂的方式释疑!


  1. 潜在意思是可以指向任意的数据类型。 ↩︎

  2. 这里的自动释放是指不需要额外用free函数释放,但我自己再Dev-c++5.11中运行,p还是指向那个地址并没变; ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值