fwiw, i've never used calloc. if i really need to memset something to 0 then i do it explicitly after the allocation.
why? the reason has nothing to do with the maintainability arguments being presented here, and has everything to do with performance. study the following code and assembly. hint: sizeof(struct foo) is a *compile-time* constant. notice how when the compiler knows it's dealing with a compile-time constant it emits code that is as efficient (and sometimes more efficient than) setting all the structure elements explicitly. notice how large the memset definition is. i don't know where the break-even is as far as when it's better to call this big function. it varies from processor to processor, and the compiler has heuristics to know when it should out-of-line a memset (with compile-time constant) versus when it should generate efficient code. it has no choice but to do a full expensive memset when the size field isn't known at compile-time. i.e. when calloc is used. -dean % cat calloc.c #include <stdlib.h> struct foo { struct foo *next; char *blah; void *whatever; }; struct foo *new_foo1(void) { struct foo *p; p = malloc(sizeof(struct foo)); memset(p, 0, sizeof(struct foo)); return p; } struct foo *new_foo2(void) { struct foo *p; p = malloc(sizeof(struct foo)); p->next = 0; p->blah = 0; p->whatever = 0; return p; } /* this function is here only to pull in the memset definition * so that i can disassemble it for you. */ void pull_in_memset(void *p, int c, size_t size) { memset(p, c, size); } int main(int argc, char **argv) { return 0; } % gcc -O calloc.c % gdb a.out GNU gdb 19991004 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux"... (gdb) b main Breakpoint 1 at 0x804844f (gdb) run Starting program: /home/dean/oneshot/a.out Breakpoint 1, 0x804844f in main () (gdb) disass new_foo1 Dump of assembler code for function new_foo1: 0x80483f8 <new_foo1>: push %ebp 0x80483f9 <new_foo1+1>: mov %esp,%ebp 0x80483fb <new_foo1+3>: push $0xc 0x80483fd <new_foo1+5>: call 0x8048310 <malloc> 0x8048402 <new_foo1+10>: movl $0x0,(%eax) 0x8048408 <new_foo1+16>: movl $0x0,0x4(%eax) 0x804840f <new_foo1+23>: movl $0x0,0x8(%eax) 0x8048416 <new_foo1+30>: leave 0x8048417 <new_foo1+31>: ret End of assembler dump. (gdb) disass new_foo2 Dump of assembler code for function new_foo2: 0x8048418 <new_foo2>: push %ebp 0x8048419 <new_foo2+1>: mov %esp,%ebp 0x804841b <new_foo2+3>: push $0xc 0x804841d <new_foo2+5>: call 0x8048310 <malloc> 0x8048422 <new_foo2+10>: movl $0x0,(%eax) 0x8048428 <new_foo2+16>: movl $0x0,0x4(%eax) 0x804842f <new_foo2+23>: movl $0x0,0x8(%eax) 0x8048436 <new_foo2+30>: leave 0x8048437 <new_foo2+31>: ret End of assembler dump. (gdb) disass memset Dump of assembler code for function memset: 0x189fec <memset>: push %ebp 0x189fed <memset+1>: mov %esp,%ebp 0x189fef <memset+3>: push %edi 0x189ff0 <memset+4>: push %esi 0x189ff1 <memset+5>: mov 0x10(%ebp),%esi 0x189ff4 <memset+8>: mov 0x8(%ebp),%edi 0x189ff7 <memset+11>: movzbl 0xc(%ebp),%eax 0x189ffb <memset+15>: cld 0x189ffc <memset+16>: cmp $0xb,%esi 0x189fff <memset+19>: jbe 0x18a024 <memset+56> 0x18a001 <memset+21>: mov %eax,%edx 0x18a003 <memset+23>: shl $0x8,%edx 0x18a006 <memset+26>: or %edx,%eax 0x18a008 <memset+28>: mov %eax,%edx 0x18a00a <memset+30>: shl $0x10,%edx 0x18a00d <memset+33>: or %edx,%eax 0x18a00f <memset+35>: mov %edi,%ecx 0x18a011 <memset+37>: neg %ecx 0x18a013 <memset+39>: and $0x3,%ecx 0x18a016 <memset+42>: sub %ecx,%esi 0x18a018 <memset+44>: repz stos %al,%es:(%edi) 0x18a01a <memset+46>: mov %esi,%ecx 0x18a01c <memset+48>: shr $0x2,%ecx 0x18a01f <memset+51>: repz stos %eax,%es:(%edi) 0x18a021 <memset+53>: and $0x3,%esi 0x18a024 <memset+56>: mov %esi,%ecx 0x18a026 <memset+58>: repz stos %al,%es:(%edi) 0x18a028 <memset+60>: mov 0x8(%ebp),%eax 0x18a02b <memset+63>: lea 0xfffffff8(%ebp),%esp 0x18a02e <memset+66>: pop %esi 0x18a02f <memset+67>: pop %edi 0x18a030 <memset+68>: leave 0x18a031 <memset+69>: ret End of assembler dump. (gdb)