3 ms·
FTA: Then there is also calloc(), which allocates memory that has been zeroed. For whatever reason, it has a slightly different interface: void* calloc(size_
by Someone 4y ago
FTA: Then there is also calloc(), which allocates memory that has been zeroed. For whatever reason, it has a slightly different interface:
void* calloc(size_t num, size_t size);
Its interface is different because, historically, it was (more or less; prototypes didn’t exist yet and I’m not sure they used unsigned, for example):
void* alloc(unsigned int num);
void* calloc(unsigned int num, unsigned int size);
and ‘int’ was 16-bits, but pointers 32 bits. So, alloc could only allocate up to 65,535 bytes, calloc up to 65,535 items of size up to 65,535. So, it allowed you to allocate much larger arrays.
- adamrezich 4y agothanks, always wondered about this!
- amscanne 4y agoI also wondered quite a bit about this difference. One interesting advantage of this alternate API is that calloc can always check for overflows, since a common pattern might be “calloc(user_input, sizeof(type))”, where using the older API without an overflow check on the multiplication would be perfect for constructing a buffer overflow. With respect to your explanation, I imagine there are some cases (maybe something older?), but in my experience the norm for an int on a system with 32-bit pointers is also 32-bits.
- ksherlock 4y ago8086 has 16-bit registers and 16-bit near pointers but there are also 32-bit far pointers using the segment register. PDP-11, where calloc most likely originated, had 16-bit integers and 16-bit pointers. Apparently, later PDP-11s could be split into 64k of code space and 64k of data space (like the Harvard architecture) but that would still use 16-bit pointers.