我是初学者C程序员,我认为情况确实如此,但如果可能的话,我会想要一些肯定.
如果它们是相同的,为什么不采取一个参数呢?
人们大多使用分配例程来为一定数量的项目分配空间,因此calloc()
可以很好地指定.因此,例如,如果您想要100个整数的空间或20个自己的结构:
int *pInt = calloc (100, sizeof(int)); tMyStruct *pMyStruct = calloc (20, sizeof(tMyStruct));
这段代码实际上看起来比同等的malloc()
调用稍微"好" :
int *pInt = malloc (100 * sizeof(int)); tMyStruct *pMyStruct = malloc (20 * sizeof(tMyStruct));
虽然,对于经验丰富的C编码员来说,没有真正的区别(当然,除了零初始化).
我不得不说我从来没有在野外使用过calloc,因为我几乎总是在创造一个struct
没有意义的地方.我更喜欢手动初始化所有字段以确保获得我想要的值.
对于发布的优秀响应,我想在使用calloc(nelem, elsize)
与malloc(nelem * elsize)
:质量实现之间增加一点差异,这calloc
将确保如果你的nelem
并且elsize
大到足以在乘法时引起整数溢出,它将失败而不是导致分配不足,作为一个天真的malloc
调用会.
只是单单这个功能就足以让我喜欢calloc
到malloc
.背景阅读.
calloc(4,6)和calloc(6,4)不一样:
在典型的32位/ 64位系统上,第一个将分配32个字节,第二个24个字节.
void *calloc(size_t nelem, size_t elsize);
关键点是calloc必须返回内存,就像它正确对齐为数组一样.它意味着分配一个数组并按如下方式使用:
A *p = (A*)calloc(count, sizeof(A)); for (int i = 0; i < count; ++i) { f(&(p[i])); // f(p + i) is also valid }
要么
A *p = (A*)calloc(count, sizeof(A)); for (A *q = p; q != p + count; ++q) { f(q); }
calloc应该考虑到目标系统的填充和其他操作要求来分配数组.所以在大多数32位机器上,需要将6字节结构填充到8个字节,它将分配4个8字节的批次.
第一个参数是sizeof()的calloc很可能是一个bug,应该进行调查.
calloc,其中第二个参数不是sizeof(atype)是未定义的.它充满了隐藏的假设,对港口来说很危险.
澄清: 在典型的32位/ 64位系统上,结构很可能被填充并与32位的倍数对齐.因此,在这些系统上,sizeof 不会返回6个字节.实际上,如果编译器/平台需要,则无法保证编译器不会填充并对齐到16个字节的某个倍数.
我的答案是基于你不应该对结构大小做出假设的事实.它们可以通过编译器选项或目标平台进行更改.只要确保你的第二个参数是sizeof表达式,不要做出假设.
从标准:
calloc()函数应为nelem元素数组分配未使用的空间,每个元素的大小(以字节为单位)为elsize.该空间应初始化为所有位0.
如果分配成功,则返回的指针应适当对齐,以便可以将其指定给指向任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(直到明确释放空间为止)或重新分配).每个这样的分配都应该产生一个指向与任何其他对象不相交的对象的指针.返回的指针应指向分配空间的开始(最低字节地址).
尽管接受了答案(我认为这是正确的),但由于对齐,似乎存在关于分配了多少字节的混淆.所以这是我的32位Linux与gcc-4.3的一点测试:
#include#include int main() { char* p1 = calloc(6, 4); char* p2 = calloc(4, 6); char* p3 = calloc(1,1); printf("%p, %p, %p\n", p1, p2, p3); return 0; }
结果是:
0x826b008, 0x826b028, 0x826b048
这表明,无论calloc(6,4)
和calloc(4,6)
分配相同量的存储器,这是舍入到32个字节我的系统上.将数字更改为calloc(3,4)
和calloc(4,3)
将产生以下结果:
0x95d2008, 0x95d2018, 0x95d2028
这表明当请求12并分配给程序时保留16个字节.在任何一种情况下,两者calloc(a,b)
和calloc(b,a)
调用都会对内存使用产生相同的影响.
由Jonathan Leffler添加,因为300个字符永远不够.
考虑一下这个程序,它会像一个名副其实的筛子一样泄漏内存,但它表明了一点:
#include#include int main() { int i, j, k; for (i = 1; i < 17; i++) for (j = 1; j < 9; j++) for (k = 0; k < 4; k++) printf("(%2d,%d)%d: %p\n", i, j, k, calloc(i, j)); return(0); }
在Windows上,在Cygwin下,这开始于分配相隔16个字节的块(实际上,第二个块在第一个块之后是24个字节,但此后,它们相隔16个字节).分配(2,7)时,块地址开始递增24个字节; 同样地,(3,4)分配16个字节的块,但是(3,5)分配24个字节的块.并且,对于记录,(4,6)和(6,4)返回指针间隔32个字节.
这只是表明存在与分配调用相关的一些开销.如果你看一下k&R中malloc()等的原型实现,你会发现块的大小存储在你有权使用的内存之前.不同的实现不同地做这些事情; 那些担心内存踩踏的人会避免将控制数据存储在用户可能造成严重破坏的地方附近.
当你调用calloc(4,6)时,你只能可靠地访问24个字节的数据.即使您的实现提供了相距32个字节的返回值,您也可能无法安全地使用超过您请求的24个字节.如果你写出你请求的边界,malloc()的调试版本将会观察到.