Although I'm not entirely sure what you mean by "type safe"1,2 in this context, you can use const with the appropriate ...ptr_t type to ensure that the (constant) value you provide is valid for the pointer.
Take the following code, for example:
#include <iostream>
#include <cstdint>
// I added an extra zero to your constant - now it's too big for a 32-bit pointer
constexpr uintptr_t reg_a_addr = 0x800000000; // uintptr_t is platform-specific
uint32_t* const ptr_reg_a = reinterpret_cast<uint32_t* const>(reg_a_addr);
// ^ Note that "const unit32_t* ptr_reg_a ..." declares a pointer to a constant;
// the version I have given defines a constant pointer to (potentially) writable memory.
int main()
{
std::cout << ptr_reg_a << "\n";
return 0;
}
When targeting the x64 platform with MSVC, this compiles without warning and produces the expected output:
0000000800000000
However, when targeting the x86 (32 bit) platform, the compiler will issue warnings that the value is too big:
warning C4305: 'initializing': truncation from '__int64' to 'const
uintptr_t'
warning C4309: 'initializing': truncation of constant
value
And, indeed, the output will be the truncated value:
00000000
As to whether or not it is practical – well, it compiles but trying to use a constexpr with reinterpret_cast doesn't, so I guess it is!
Note that the clang-cl compiler in Visual Studio 2022 (when targeting 32 bits) gives an 'equivalent' warning for the constant being too big:
warning : implicit conversion from 'long long' to 'const uintptr_t'
(aka 'const unsigned int') changes value from 34359738368 to 0
[-Wconstant-conversion]
1 Maybe, by "type safe," you mean that reassigning a new value to that pointer will be prevented at compile time … in which case: Yes, it is type safe, as code like the following will not compile:
uint32_t q = 42;
ptr_reg_a = &q;
error : cannot assign to variable 'ptr_reg_a' with const-qualified
type 'uint32_t *const' (aka 'unsigned int *const')
2 If you are asking whether or not using const rather than constexpr will make such a pointer any less strictly typed, then: No, it won't. However, (IIRC) the C++ Standard does impose stricter requirements for diagnostics on potential misuse of constexpr values … but many (if not most) mainstream compilers will, if warnings are fully enabled, provide suitable diagnostics for cases of (say) violation of strict aliasing rules, or other usage of such a pointer that exhibits undefined behaviour.
reinterpret_cast) to be handled in compile time. In another way, it might be UB in runtime, so how to implement it in compile time which doesn't allow UB in all the cases?constcompiles fine but is it practical?" -- You might have to define what you mean by "practical". I'd be inclined to say that usingconstis practical because it compiles fine, combined with it being not excessively long. Apparently you have a different definition of "practical" than me, so it would help if you included your definition in the question.