Note that this is purely an academic question, from a language lawyer perspective. It's about the theoretically safest way to accomplish the conversion.
Suppose I have a void*
and I need to convert it to a 64-bit integer. The reason is that this pointer holds the address of a faulting instruction; I wish to report this to my backend to be logged, and I use a fixed-size protocol - so I have precisely 64 bits to use for the address.
The cast will of course be implementation defined. I know my platform (64-bit Windows) allows this conversion, so in practice it's fine to just reinterpret_cast<uint64_t>(address)
.
But I'm wondering: from a theoretical standpoint, is it any safer to first convert to uintptr_t
? That is: static_cast<uint64_t>(reinterpret_cast<uintptr_t>(address))
. https://en.cppreference.com/w/cpp/language/reinterpret_cast says (emphasis mine):
Unlike static_cast, but like const_cast, the reinterpret_cast expression does not compile to any CPU instructions (except when converting between integers and pointers or on obscure architectures where pointer representation depends on its type).
So, in theory, pointer representation is not defined to be anything in particular; going from pointer to uintptr_t
might theoretically perform a conversion of some kind to make the pointer representable as an integer. After that, I forcibly extract the lower 64 bits. Whereas just directly casting to uint64_t
would not trigger the conversion mentioned above, and so I'd get a different result.
Is my interpretation correct, or is there no difference whatsoever between the two casts in theory as well?
FWIW, on a 32-bit system, apparently the widening conversion to unsigned 64-bit could sign-extend, as in this case. But on 64-bit I shouldn't have that issue.