Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> but it is non-ideal that I’m only allowing half the range of size_t.

I am fairly certain that in C it's actually impossible to have an object whose size is larger than half of the range of size_t unless ptrdiff_t is wider than size_t, which normally isn't. Unless, of course, C standard decided to make subtracting two valid pointers into the same array (or one past the end) a potential UB, just because.



Actually, that is UB.

> If the result is not representable in an object of that type, the behavior is undefined. In other words, if the expressions P and Q point to, respectively, the i-th and j-th elements of an array object, the expression (P)-(Q) has the value i - j provided the value fits in an object of type ptrdiff_t.


Although, I can't help thinking you're going to run into bigger problems than that if the size of your buffer has grown to 9,223,372,036,854,775,807 bytes.


Well, but what if you're working with a 16-bit microcontroller? Apparently, there were quite some heated discussions about that which is why, while size_t was required to be at least 16 bits, ptrdiff_t was required to be at least 17 bits, in C99... and then it was reverted back to 16 bits in C23. See e.g. [0]

This trade-off is actually making me sad. One can either have all the sizes and offsets fit into (unsigned/signed) integers, or one can have objects spanning more than half of the memory space. I think for my language I'd pick "all sizes/offsets are signed, and so yeah, you can't span all of the memory with a single char array".

[0] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2808.htm


Interesting. I hadn't thought of that.

... although I can't help thinking you have larger problems if you have two objects larger than 16k in the same array in a machine that has at most 64k of memory. :-P Or a char array greater than 32k for that matter.

I do appreciate the theoretical horror, but thank you anyway, C23! Having to cast your size_t's to ptrdiff_t's before you subtract them in order to preserve portability seems ... impractical.


You always could subtract two size_t's: they're unsigned, after all, and such behaviour always have been defined, and the result is also unsigned. But if you want to subtract pointers, apparently you better convert them to uintptr_t first.


lol. You can't always subtract two size_t's. (size_t)3 - (size_t)4. And (ptrdiff_t)((size_t)3-(size_t)4) actually would be undefined behavior in C++20!


The "(size_t)3 - (size_t)4" is defined to be the same as "-(size_t)1", which is defined, and the same as "(size_t)1 + ~(size_t)1". Also, "(ptrdiff_t)((size_t)3-(size_t)4)" is defined both before and after C++20:

    If the destination type is signed, the value does not change if the source integer can be represented in the destination type. Otherwise the result is [implementation-defined (until C++20)] [the unique value of the destination type equal to the source value modulo 2^n where n is the number of bits used to represent the destination type (since C++20)] (note that this is different from signed integer arithmetic overflow, which is undefined).


However, the value of (ptrdiff_t)((size_t)3-(size_t)4) is positive if ptrdiff_t has at least 17 bits, and size_t only has 16 bits, and negative whenever ptrdiff_t and size_t have the same number of bits.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: