I recently remembered something I'd half-forgotten. A size_t is not guaranteed
to be the same size as a pointer. A uintptr_t is.
size_t and uintptr_t are the same for all platforms that D currently supports.
But this may not always hold true, and besides, it is better self-documenting
when using uintptr_t for "holds a pointer" as opposed to size_t as "holds an
offset to a pointer".
uintptr_t may be found in:
import core.stdc.stdint : uintptr_t;
as it is part of Standard C.
When are they not the same?
1. In 16 bit code that supports the 'far' memory model, where pointers are a
segment/offset pair and uintptr_t would be 32 bits and size_t 16. Of course, D
does not support 16 bit code so this is irrelevant for D.
2. There is a memory model in the 32 bit x86 where segment/offset pairs are
used, and uintptr_t would be >=48 bits and size_t 32. This is used sometimes in
kernel programming.
3. Any system that would have some sort of banked switched memory scheme.
Ok, I admit these are not likely to emerge. But I'd like our code to be
pedantically, nitpickingly correct, as well as self-documenting.
druntime/phobos pervasively misuse size_t. I've put in a PR to address some:
https://github.com/dlang/phobos/pull/4430
=========================================================
A related issue is I see much code of the form:
cast(size_t)ptr & 3
to check alignment. A better (possibly faster) method is:
cast(uint)ptr & 3
because even 64 bit CPUs often operate faster with 32 bit operations (thanks to
some research by Andrei).
=========================================================
Call to action: do things like:
grep cast(size_t) *.d
to look for misuse, and submit PRs to fix!