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!

Reply via email to