we miss you on icb
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!
addr = base << 4 + offset> 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).
However good their intentions might have been...programming that thing was hell.
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=10...