2 ms·
There is a simpler explanation. On 16-bit systems SIZE_MAX is often 65535. You can't allocate a 64K (65536) block with malloc() but you can with calloc().
by kevin_thibedeau 4y ago
There is a simpler explanation. On 16-bit systems SIZE_MAX is often 65535. You can't allocate a 64K (65536) block with malloc() but you can with calloc().
- loeg 4y agoI'm not confident it's valid to allocate objects larger than SIZE_MAX/2 on any platform.
- klodolph 4y agoWhy not? The first argument that comes to mind is the existence of ptrdiff_t, but you’re not guaranteed to get a valid ptrdiff_t just by subtracting two pointers in the same array!
- teo_zero 4y agoNot objects but memory. It was common in 16-bit era. And you would access it through memory segmentation, with two registers: one pointing at the segment beginning, the other being the offset. In code: addr = base << 4 + offset
- jwilk 4y agoAs a data point, C23 added explicit wording about overflow handling in calloc(): > The calloc function returns […] a null pointer […] if the mathematical product of nmemb * size is not representable as a value of type size_t. So apparently the Committee is OK with allocating more than SIZE_MAX/2 (but not more than SIZE_MAX).
- klodolph 4y agoDoes such a system exist?
- Retr0id 4y ago8086 (and any subsequent intel chip, running in real mode)
- bell-cot 4y agoOr worse - Intel's 80286, in protected mode. However good their intentions might have been...programming that thing was hell.
- ogurechny 4y agoTo generalize, that odd thing happens on systems whose native integer range is smaller than the amount of addressable memory, and where some kind of combination of bank/segment value and offset value defines that address (usually in the manner dictated by hardware). On 16 bit x86, the biggest value processor can count to is 65535, but the number of those values (from 0 to 65535) is 65536, and so is the number of byte offsets in one segment. Memory handling functions had to deal with segment and offset calculations, overflows, underflows, and wraparounds in wider address space, and could allocate the full 64K segment when not limited by maximum value of a single variable (it was not guaranteed, though, as some allocators could reserve some space for their own headers). The value of 65535 was probably inherited as lower limit for SIZE_MAX in standard because 8 bit systems were not considered real targets for “real C” (as opposed to microcontroller-specific subsets of C). Of course, people then wrote C compilers for those systems, and various AVRs and STMs were made to support pointer-heavy and subroutine-heavy code better while still being simple. One could get rid of those sharp corners by extending the compiler to present any system as having simple flat memory and integers that are big enough, but it would be the direct opposite of why people use C language. The performance would suffer, too. Random oldnewthing link to make this comment seem well-sourced: https://devblogs.microsoft.com/oldnewthing/20200728-00/?p=104012 https://devblogs.microsoft.com/oldnewthing/20200728-00/?p=10...
- jasone 4y agoThis might not be the primary initial motivation for calloc(), but I think you're right about why it takes two arguments.
- kragen 4y agomaybe not: https://news.ycombinator.com/item?id=33580653 https://news.ycombinator.com/item?id=33580653 we miss you on icb