
I. malloc
MSDN中的malloc原型是:
无效* malloc(size_t大小);
简介:
malloc返回指向分配空间的空指针,如果没有足够的可用内存,则返回NULL. 要返回指向非void类型的指针,请对返回值使用类型强制转换. 返回值所指向的存储空间可以保证适当对齐以存储任何类型的对象. 如果size为0,则malloc在堆中分配零长度的项目,并返回指向该项目的有效指针. 始终检查malloc的返回结果,即使请求的内存量很小.
可能意味着:
malloc返回一个指针. 如果未成功分配内存或内存不足以导致分配失败,则会返回NULL指针. 否则,将返回分配的内容的第一个地址.
我应该在这里注意: 如果在malloc中将0写入size大小,它将向该变量写入0字节.
这里有歧义.
如果我向程序中编写了这样的代码行:
int * p;
p = (int *)malloc(0);
p的值是NULL吗?
由VS2013测试,它不是NULL. 为什么会这样?
MSDN中有这样一段:
malloc函数分配至少大小为字节的内存块. 由于对齐和维护信息所需的空间,该块可能大于大小字节.
这意味着malloc生成的空间量大于您编写的空间.
说明如下:
第一:
在标准的malloc实现中,不检查输入值的大小,但是在对齐后直接从堆中分配输入值.
第二:
不管输入值的大小如何,malloc的最小内部内存分配大小都是固定值(通常为8B),因为malloc需要此空间来维护堆上内存块的链表. 因此,当用户申请0B空间时,malloc分配的实际空间为8B. 如果用户请求的空间为X,则malloc分配的实际空间为(align(X)+ 8). 这就是为什么不能超出范围使用malloc分配的空间的原因: 堆的内部链表结构将被破坏.
那么,free是怎么知道要释放多少内存的呢?
看图~
malloc自动记录了此次分配的内存大小。

其次,calloc
calloc的作用是什么?
calloc在MSDN中的描述如下:
calloc
在内存中分配一个数组,并将其元素初始化为0.
void * calloc(size_t num,size_t大小);
常规例程标头兼容性
calloc
int *p = (int*)calloc(0,2*sizeof(int));
//相当于
int *p=(int *)malloc(2*sizeof(int));
memset(p,0,2*sizeof(int));
为什么我们在日常生活中看到malloc比calloc更多?由于calloc会初始化内存空间,因此也会降低程序的效率.
在某些情况下,没有必要初始化内存空间〜
三,重新分配
ANSI C说明了用于动态分配存储空间的三个功能
(1)malloc分配指定数量的内存字节. 该存储区域中的初始值不确定
(2)calloc是指定长度的对象,并分配可以容纳指定数量对象的存储空间. 该空间中的每一位都初始化为0
(3)重新分配更改先前分配的区域的长度(增加或减少). 当增加长度时,可能需要将先前分配的区域的内容移动到另一个足够大的区域,并且新添加区域中的初始值不确定.
这是以上三个功能之间的区别
realloc分配失败时,返回NULL
realloc分配失败时,原来的内存空间不改变,不释放也不会移动
如果size=0,realloc = free,只对指针指向内存进行释放
对于二级指针来说,realloc(**p,0),只会释放一维指针,不会释放内存,所以要注意内存泄露
传递给realloc的指针必须是经过malloc,calloc,realloc申请的
当ptr为NULL,realloc(ptr,10) = malloc(ptr,10)
realloc允许我们增加或减少先前分配的区域的长度(最常见的用法是增加区域).
PS: Realloc用于增加动态序列表的容量.
如果首先分配一个可以容纳长度为512的数组的空间并在运行时填充它,但是发现空间不足,则可以调用realloc扩展存储空间.
1. 如果存储区后面有足够的空间用于扩展,则可以将原始存储区扩展到高地址方向,并返回传递给它的相同指针值.
2. 如果原始存储区之后没有足够的空间,则realloc会分配另一个存储区,该存储区足够大,可以将现有5 1 2元素数组的内容复制到新分配的存储区.
由于该存储区可能会移动,因此您不应在其中使用任何指针.

注意
realloc的最后一个参数是存储区的newsize(新长度),而不是新旧长度之间的差.
作为一种特殊情况,如果ptr是一个空指针,则realloc具有与malloc相同的功能,并用于分配指定大小的存储区newsize.
四,阿洛卡
分配函数
还有另一个值得一提的功能,这就是alloca. 其调用顺序与malloc相同,但是它在当前函数的堆栈帧上而不是堆上分配存储空间.
优点是当函数返回时,它会自动释放它使用的堆栈帧,因此您不必担心释放空间. 缺点是某些系统在调用函数后无法增加堆栈帧的长度,因此它们无法支持alloca函数. 但是,许多软件包仍使用alloca功能,并且许多系统都支持它.
_alloca
在堆栈上分配内存.
void * _alloca(size_t大小);
常规例程标头兼容性
_alloca
=============================================== === =======
对于这个烂问题,请记下理解力. 这三个都在stdlib.h库中分配内存和所有函数,但是有一些细微的差异.
首先,对于malloc函数. 其原型void * malloc(unsignedintnum_bytes)
num_byte是要应用的空间大小,我们需要手动计算它,例如int * p =(int *)malloc(20 * sizeof(int)). 如果编译器默认将int设置为4字节,则计算结果为80Byte,一次应用一个
80个字节的连续空间,并且空间基地址被强制为int类型并分配给指针p. 此时,应用的内存值不确定.
对于calloc函数,其原型为void * calloc(size_t n,size_t大小);
从直觉上讲,它比malloc函数多一个参数,不需要人工计算空间大小. 例如malloc realloc calloc,如果他想申请20个int类型的空间,他将int * p =(int *)calloc(20malloc realloc calloc,sizeof(int)),这样可以节省人类的空虚
麻烦的计算. 但这不是它们之间最重要的区别. 应用后malloc的空间值是随机的,尚未初始化,但是calloc在应用后将空间一一初始化并将其值设置为0;
下面
int * p =(int *)malloc(20 * sizeof(int)); int * pp =(int *)calloc(20,sizeof(int));英蒂printf(“ malloc应用的空间值: \ n \ n”); for(i = 0; i <20; i ++){printf(“%d”,* p ++);} printf(“ \ n \ n”); printf(“ calloc值: \ n \ n”); for(i = 0; i <20; i ++){printf(“%d”,* pp ++);} printf(“ \ n”);
结果是

许会问: 既然calloc不需要计算空间,并且可以直接初始化内存以避免错误,为什么不直接使用calloc函数,malloc的用途是什么?
实际上,一切都有两个方面. 有好的方面,也必有缺点. 这就是效率. 由于calloc函数需要为每个空间初始化值,因此它必须比malloc效率低,并且在现实世界中,空间应用程序在许多情况下不需要初始值,这就是为什么许多初学者会更多地接触malloc函数的原因. 原因.
在讨论了malloc和calloc之后,让我们讨论一下realloc函数.
realloc函数本质上与上面两个不同,
原型voidrealloc(void * ptr,size_tnew_Size)用于扩展动态内存(并且应用的动态空间不足,需要空间扩展操作)
ptr是指向原始空间基址的指针,而new_size是接下来需要扩展的大小.
intmain(void)(constintsize = 2000; int * p =(int *)malloc(20 * sizeof(int)); int * pp =(int *)realloc(p,size * sizeof(int)); printf(“原始的p_Address: %x扩展的pp_Address: %x \ n \ n”,p,pp); return0;}
结果是:
从图中可以看出,扩展后的地址与原始地址不同,但这仅取决于扩展后的内存大小.
实际上:
如果大小很小,并且原始动态内存后面有可用内存,则系统将直接在原始内存空间后面扩展容量,并返回原始动态空间基址;
如果大小很大,并且原始请求的空间后面没有足够的空间,则系统将重新应用一块(20 + size)* sizeof(int)内存,并复制原始空间的内容. 原始空间是免费的. ;
如果大小很大,则系统内存应用程序将失败,并返回NULL. 原始内存不会释放.
注意: 如果扩展的存储空间小于原始空间,则会发生数据丢失. 如果直接重新分配(p,0);相当于免费(p)
=============================================== ==== =======
这三个函数的声明是:
void *重新分配(void * ptr,未签名的newsize);
void * malloc(无符号大小);
void * calloc(size_t numElements,size_t sizeOfElement);
全部在stdlib.h函数库中
它们的返回值是请求系统分配的地址. 如果请求失败,则返回NULL.
malloc用于申请新地址,参数大小为所需内存空间的长度,例如:
char * p;

p =(char *)malloc(20);
calloc与malloc相似,参数sizeOfElement是应用程序地址的单位元素的长度,而numElements是元素的数量,例如:
char * p;
p =(char *)calloc(20,sizeof(char));
此示例与上一个示例具有相同的作用
realloc是将空间重新分配给已经分配了地址的指针,参数ptr是原始空间地址,而newsize是重新应用的地址长度
例如:
char * p;
p =(char *)malloc(sizeof(char)* 20);
p =(char *)重新分配(p,sizeof(char)* 40);
请注意,此处的空间长度以字节为单位.
C的标准内存分配功能: malloc,calloc,realloc,free等.
malloc和calloc的区别是1个块和n个块之间的区别:
malloc调用的格式为(类型*)malloc(大小): 在内存的动态存储区域中分配一个长度为“ size”的连续区域,并返回该区域的第一个地址.
calloc调用形式为(type *)calloc(n,size): 在内存的动态存储区域中分配n个“大小”字节的块,并返回第一个地址.
realloc调用的形式是(type *)realloc(* ptr,size): 将ptr内存大小增加到size.
的呼叫形式
free是免费的(void * ptr): 释放ptr指向的一块内存空间.
C ++中的新增/删除功能.
1,int * p1 =(int *)malloc(0)//好的,p1! = NULL
2,int * p2 =(int *)重新分配(p1,newsize * sizeof(int));
// newsize很小,并且重新分配操作成功,p2 == p1
// newsize很大,重新分配操作成功,p2! = p1 && p2! = NULL
// newsize很大,当重新分配操作失败时,p2 == NULL
3,int * p3 =(int *)重新分配(NULL,10 * sizeof(int)); //好的,p3! = NULL
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-150402-1.html
说明美国不愿面对岛礁的12海里内是中国的了
时以为只有万恶的旧社会才会多男找一个老婆