C语言初始化自引用结构体时calloc与malloc的选型对比
calloc与malloc效果、效率对比及代码问题修正
核心特性差异
malloc:仅向系统申请指定大小的连续内存空间,不对内存内容做任何修改,返回的内存块中保留的是历史遗留的随机垃圾值。calloc:申请指定数量、指定单块大小的连续内存空间,返回前会将整块内存的所有字节置为0。
执行效率对比
- 不考虑初始化需求的前提下,
malloc理论速度更快,因为省去了整块内存清零的步骤。 - 如果你本身就需要把内存全置为0,二者实际性能差异极小:小块内存申请场景下,清零操作的开销几乎可以忽略;部分操作系统对
calloc做了底层优化,会直接映射预清零的空闲内存页,效率甚至高于手动逐字段初始化。
你给出的代码存在的问题
两个实现都存在三个共性的致命错误:
- 结构体定义语法错误:
*void name;是非法写法,指针类型标记*应该跟在类型关键字后面,正确写法为void *name;。 sizeof使用错误:函数内局部指针变量命名为person,和外层typedef的结构体类型名重名,导致sizeof(person)计算的是指针变量的长度(64位系统下为8字节),远小于结构体实际占用的内存大小,运行时会出现内存越界写入。- 两个实现都没有判断内存申请失败的返回值,申请失败时
malloc/calloc会返回NULL,直接操作空指针会触发程序崩溃。
方案选择建议
- 你当前的结构体只有两个指针字段,且申请内存后已经手动给两个字段赋值为
NULL,这种场景选malloc更合理,calloc的全块清零属于重复操作,会产生不必要的开销。 - 如果后续结构体可能新增字段,优先选
calloc:哪怕你新增指针字段后忘记手动初始化,calloc默认的零值也能保证指针为NULL,不会出现野指针问题,代码健壮性更高。
注意:C标准仅保证零值的整型常量等于0、零值的指针常量等于
NULL,不要依赖calloc的零初始化给浮点数、带自定义构造逻辑的结构体等非基础类型字段设默认值,这类场景必须手动赋值。
修正后的参考代码
malloc版本:
typedef struct _person { void *name; struct _person *child; } person; person *new_person() { person *p = malloc(sizeof(person)); if (p == NULL) return NULL; p->name = NULL; p->child = NULL; return p; }
calloc版本(无需手动给指针字段赋NULL):
person *new_person() { person *p = calloc(1, sizeof(person)); if (p == NULL) return NULL; return p; }
内容的提问来源于stack exchange,提问作者user14857007
相关产品推荐
相关产品推荐

