函数malloc()和calloc()都可以用来动态分配内存空间,但两者稍有区别。首先看他们的函数申明:
void* malloc(size_t size);
void* calloc(size_t numElements, size_t sizeOfElement);
可以看到,malloc()函数只有一个函数,即请求分配的内存空间大小;而calloc()函数有两个参数,分别表示元素的数目和每一个元素的大小,这两个参数的乘积才是请求分配的内存空间大小。如果函数调用成功,函数malloc()和函数calloc()都将返回所分配的内存空间的首地址。
函数malloc()和函数calloc() 的主要区别是前者不能初始化所分配的内存空间,而后者能。如果由malloc()函数分配的内存空间原来没有被使用过,则其中的每一位可能都是0;反之, 如果这部分内存曾经被分配过,则其中可能遗留有各种各样的数据。也就是说,使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常进 行,但经过一段时间(内存空间还已经被重新分配)可能会出现问题。
函数calloc() 会将所分配的内存空间中的每一位都初始化为零,也就是说,如果你是为字符类型或整数类型的元素分配内存,那麽这些元素将保证会被初始化为0;如果你是为指 针类型的元素分配内存,那麽这些元素通常会被初始化为空指针;如果你为实型数据分配内存,则这些元素会被初始化为浮点型的零。
下面用redis 源代码下的sds.c中的sdsnewlen函数来举例,说明两者之间的区别。代码如下:
sds sdsnewlen(const void *init, size_t initlen) {
struct sdshdr *sh;
if (init) {
sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
} else {
sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
}
if (sh == NULL) return NULL;
sh->len = initlen;
sh->free = 0;
if (initlen && init)
memcpy(sh->buf, init, initlen);
sh->buf[initlen] = '\0';
return (char*)sh->buf;
}
这里zmalloc相当于malloc,而zcalloc相当于calloc。该函数的作用是,当void不为空时,即初始化内容不为空,函数调用zmalloc,然后会调用memcpy函数把init的内容拷贝到sh->buf中;否则,调用zcalloc函数,因为zcalloc内部会初始化为分配内容为0,即sh->buf中的内容为0。