做以下两种操作有何区别:
ptr = malloc(MAXELEMS * sizeof(char *));
并且:
ptr = calloc(MAXELEMS, sizeof(char*));
何时使用calloc
比malloc
更好,反之亦然?
malloc()
和calloc()
是C标准库中的函数,允许动态内存分配,这意味着它们都允许在运行时进行内存分配。
它们的原型如下:
void *malloc( size_t n);
void *calloc( size_t n, size_t t)
这两者主要有两个不同之处:
行为(Behavior):malloc()
分配一个内存块,但不初始化它,从该块读取内容将导致垃圾值。另一方面,calloc()
分配一个内存块并将其初始化为零,显然读取该块的内容将导致零。
语法(Syntax):malloc()
接受 1 个参数(要分配的大小),而 calloc()
接受两个参数(要分配的块数和每个块的大小)。
如果成功,两者返回的值都是指向已分配内存块的指针。否则,将返回NULL表示内存分配失败。
示例:
int *arr;
// allocate memory for 10 integers with garbage values
arr = (int *)malloc(10 * sizeof(int));
// allocate memory for 10 integers and sets all of them to 0
arr = (int *)calloc(10, sizeof(int));
malloc()
和 memset()
可以实现与 calloc()
相同的功能:// allocate memory for 10 integers with garbage values
arr= (int *)malloc(10 * sizeof(int));
// set all of them to 0
memset(arr, 0, 10 * sizeof(int));
malloc()
比calloc()
更快,因此最好使用它。如果需要零初始化值,请改用calloc()
。calloc()
函数在<stdlib.h>
头文件中声明,相较于malloc()
函数它有以下几个优点:
一个还未提到的区别是:大小限制
void *malloc(size_t size)
只能分配最多 SIZE_MAX
大小的内存。
void *calloc(size_t nmemb, size_t size);
可以分配最多 SIZE_MAX*SIZE_MAX
大小的内存。
许多具有线性寻址的平台很少使用这种能力。这些系统通过 nmemb * size <= SIZE_MAX
来限制 calloc()
的使用。
考虑一种名为 disk_sector
的 512 字节类型,代码想要使用 大量 扇区。在这里,代码只能使用最多 SIZE_MAX/sizeof disk_sector
个扇区。
size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);
size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);
现在,如果这样的系统可以提供如此大的分配是另一回事。大多数今天不会这样做。然而,在SIZE_MAX
为65535时,这种情况已经发生了很多年。考虑到摩尔定律,预计到2030年某些内存模型将出现SIZE_MAX == 4294967295
和100 GB内存池。
size_t
大于 32 位。唯一的问题是,使用 calloc
并且乘积超过 SIZE_MAX
的值是否可靠地产生零,而不是返回指向较小分配的指针。 - supercatSIZE_MAX
的分配。它当然不要求在任何情况下都必须成功分配这样的内存;我不确定强制要求不能处理这种分配的实现必须返回NULL
是否有任何特定的好处(特别是考虑到一些实现通常会让malloc
返回指向尚未提交的空间的指针,而当代码实际尝试使用它时可能无法使用)。 - supercatSIZE_MAX (4G-1)
以外内存指针的calloc()
函数的架构。 - chux - Reinstate Monicasize_t
定义为uint64_t
? - supercatmalloc
和 calloc
都用于分配内存,但是 calloc
会初始化所有位为零,而malloc
不会。
可以说 calloc
相当于使用 memset
设置为0 的 malloc(其中 memset 将指定的内存位设置为零)。
因此,如果不需要初始化为零,则使用 malloc 可能更快。
malloc
系列函数的返回值进行类型转换。 - phuclvptr = calloc(MAXELEMS, sizeof(*ptr));
。其中,calloc
用于动态分配内存,MAXELEMS
表示需要分配的元素个数,sizeof(*ptr)
表示每个元素所占内存的大小,ptr
表示指向分配内存的指针。 - chqrlie