将指针类型转换为 uint64_t 时,通过 uintptr_t 是否会带来任何安全性?

use*_*520 3 c++ language-lawyer

请注意,从语言律师的角度来看,这纯粹是一个学术问题。这是理论上最安全的完成转换的方法。

假设我有 avoid*并且需要将其转换为 64 位整数。原因是该指针保存了错误指令的地址;我希望将此报告给我的后端进行记录,并且我使用固定大小的协议 - 因此我有精确的 64 位可用于该地址。

当然,演员阵容将由实现定义。我知道我的平台(64 位 Windows)允许这种转换,所以在实践中,只需reinterpret_cast<uint64_t>(address).

但我想知道:从理论的角度来看,首先转换为更安全吗uintptr_t?那是:static_cast<uint64_t>(reinterpret_cast<uintptr_t>(address))https://en.cppreference.com/w/cpp/language/reinterpret_cast说(强调我的):

与 static_cast 不同,但与 const_cast 类似,reinterpret_cast 表达式不会编译为任何 CPU 指令(除非在整数和指针之间进行转换,或者在指针表示取决于其类型的模糊体系结构上)。

因此,从理论上讲,指针表示并没有被定义为任何特定的东西;理论上,从指针 到uintptr_t 可能会执行某种类型的转换,以使指针可表示为整数。之后我强行提取低64位。而直接转换为uint64_t不会触发上述转换,因此我会得到不同的结果。

我的解释是否正确,或者理论上这两种演员之间没有任何区别?

FWIW,在 32 位系统上,显然向无符号 64 位的扩大转换可以进行符号扩展,就像在本例中一样。但在 64 位上我不应该遇到这个问题。

Sne*_*tel 6

你\xe2\x80\x99正在解析该段落(对于cppreference来说非常不正式)。它\xe2\x80\x99s试图得到的东西很简单,其他转换可能涉及转换操作(浮点/整数的东西,符号扩展,指针调整),而reinterpret_cast具有直接重用位的风格。

\n

如果将指针重新解释为整数并且整数类型不够大,则会出现编译时错误。如果它足够大,你\xe2\x80\x99就可以了。除了保证(如果存在)它\xe2\x80\x99uintptr_t足够大之外,\xe2\x80\x99s 没有什么神奇的,如果你重新转换为较小的类型,无论如何你都会失去它。要么 64 位就足够了,在这种情况下,无论您做什么,您都可以获得相同的保证,否则\xe2\x80\x99 就不行,并且无论您做什么,您\xe2\x80\x99 都会被搞砸。如果你的实现愿意在reinterpret_cast中做一些奇怪的事情,这可能会给出与(比如说)bit_cast不同的结果,那么这两种方法都不会保证也不会阻止这种情况。

\n

当然,\xe2\x80\x99 并不是说​​两者保证相同。考虑具有 32 位指针的 DS9k-ish 架构,其中指向 uint64_t 的指针的 reinterpret_cast 导致指针位在低字和高字中重复。如果您直接访问 uint64_t,则\xe2\x80\x99d 将获得两个副本,如果您访问 32 位 uintptr_t,则上半部分为零。在这种情况下,哪个是 \xe2\x80\x9cright\xe2\x80\x9d 将是个人意见的问题。

\n