About size_t and ptrdiff_t
medium.com
medium.com
size_t represents the size of objects in memory. So of course it scales with virtual memory space.
ssize_t is like size_t (same width), but signed. It's useful for routines that want to return a size_t or error (network routines like send/recv).
ptrdiff_t is specifically for the result of subtracting one pointer from another. Obviously it scales with pointer size as well.
size_t is an unsigned type - it is used to represent the sizes of objects in memory, which can never be negative.
Another funny thing I just discovered: You can't declare an array like "char somearray[SIZE_MAX]"; clang gives "error: array is too large (18446744073709551615 elements)". But you can use SIZE_MAX as an array index (although it gives a warning "array index -1 is past the end of the array"). Also, trying to declare an array like "char somearray[SIZE_MAX/8]" inside a simple main() just sends clang into 100% cpu...
For greater-than/smaller-than comparisons, I see the utility of working in the signed space though. I guess it all depends on expectations. If you have a pointer to the very last byte of a 2^32 address space (0xFFFF_FFFF), and subtract a pointer to the second byte from the start (0x0000_0001), you'll end up with a diff that should be "SIZE_MAX-2", but will be parsed as "-2" in the signed interpretation.
Yeah, true. I recalled there being separate instructions and then messed up my napkin math to check if it made a difference within the relevant range.
This page is a much shorter summary than the article: http://www.gnu.org/software/libc/manual/html_node/Important-...
Also an important note: if you use special types like ptrdiff_t and size_t, you must not use the underlying native type printf specifiers when printing them. e.g. never print a ptrdiff_t using %ld, use the ptrdiff_t format specifier %td. (because some systems may say ptrdiff_t is long while others may say long long, and all your printf strings will then print compile time warnings.) Also see https://en.wikipedia.org/wiki/Printf_format_string#Length_fi...
Plus, the medium article is a complete copy/paste of this 2009 article: http://www.viva64.com/en/a/0050/ — looks like the account https://news.ycombinator.com/user?id=PVS-Studio is copying from viva64 and posting to medium for a lot of old articles.
I guess that is one way to write articles.
Seems legit unless someone's actually impersonating someone else. I don't quite understand why, if Karpov wrote the original article and is a Medium contributor, Vasiliev rather than Karpov should be doing the reposting. (You could imagine something like this: K is a senior technical guy at PVS-Studio, V is a more junior technical guy or is in the marketing department; in 2009 they thought it better to post things under K's name to get it out there, but now K wants only the more impressive articles under his name and lets V post the others. But this doesn't feel terribly plausible.)
Yes, but if you're just storing the delta between two pointers and then adding/subtracting this diff to get from one to the other it will still work. Of course it will also work using size_t.
This would require keeping track of which one is bigger somewhere else unless you had enough room to store a sign. Seems like a pretty goofy way to go about it if you're going to the trouble of making a type specifically to hold a delta.
Practically, amd64 is already limited to more like 48 bits (4 levels of 9 bit pagetables describing 12 bit pages) of memory.
Nope. You assume the math is being done mod 2^32 or 2^64 and it just works weather you use signed or unsigned integers. Pro-tip: the hardware does the exact same bit operations for signed and unsigned addition and subtraction (except for carry/borrow which aren't part of the C standard anyway). integer overflow is undefined, but this behavior is AFAICT universal anyway. If it didn't behave this way then a difference would in fact need the extra bit.
1. Their "headline" recommendation near the start is that you should write things like for (ptrdiff_t i=0; i<...; ++i) { ... a[i]; ... }. No, for this purpose you should almost certainly be using size_t rather than ptrdiff_t. The article nowhere gives any reason for preferring ptrdiff_t to size_t in this context. (There might be some; e.g., if you're processing that array in reverse order, you might want to test whether i>=0, and that won't give useful results if i is of an unsigned type. But you won't learn that from the article.)
2. The article claims that size_t and uintptr_t are synonyms, and likewise for ptrdiff_t and intptr_t. I dare say in practice they're always equivalent types, but they certainly don't mean the same thing and encouraging readers to think they do is a bad idea.
3. Similarly, the article says that a size_t or ptrdiff_t "can store a pointer". There are -- as the article admits -- integral types actually guaranteed to be usable in this way, namely intptr_t and uintptr_t. There is no guarantee that you can do that with size_t or ptrdiff_t, and no good reason why you should try.
4. The article says that ptrdiff_t "could store the maximum size of a theoretically possible array of any type". No, that would be size_t.
5. The article lists things that size_t and ptrdiff_t are "usually used for". The difference between the two lists is that the one for ptrdiff_t includes "size storage", which is exactly backwards. (You'd think the name size_t might be a clue.)
6. Those lists include, in both cases, "storing pointers". No: use pointer types for storing pointers, and if you really truly need to force them into integral types then use intptr_t or uintptr_t.
7. In the second example of a "sleeping error" -- the one with variables A and B -- the more fundamental problem isn't the failure to use size_t/ptrdiff_t, it's the fact that the expression A+B is of an unsigned type but is being used to hold a negative array offset. It's true that using size_t instead of unsigned will probably make the error go away, but the right way to make it go away is never to have the equivalent of ((unsigned)-2) in your code to begin with. You want a signed type for that, and int will do just as well as ptrdiff_t.
8. The final section of the article makes it clear that its real goal is to convince developers that (1) we should use size_t and ptrdiff_t if we care at all about portability and future-proofing, but (2) converting code to do so is too painful for human beings, so (3) you should buy their product.
It's maybe a bit unfair to classify that as an "error", but I don't think I would want to entrust static analysis of integer-type issues to software written by someone who could write this article.
"ptrdiff_t type...ptrdiff_t will take 32 bits, on a 64-bit one 64 bits" -- that's not really true as that would made it equivalent to size_t. So in reality its 31 bits and 63 bits.
[EDITED to add: Having said which, the above isn't really any wronger than the OP which is full of mistakes.]
They author states "The type’s size is chosen so that it could store the maximum size of a theoretically possible array of any type" and the same is said for ptrdiff_t, which is quit confusing.
Now I realise that in reality they both use 64 bits, it is somewhat strange to use the same text for both.