__uint128_t的reinterpret_cast

据我所知,reinterpret_cast 不得导致数据丢失。

因此不可能在 X86_64 中编译这样的代码,因为整数小于指针

#include <cstdio>
int main() {
    int a = 123;
    int res = reinterpret_cast<int>(reinterpret_cast<void*>(a));
    printf("%d", a == res);
}

问题是:为什么我可以在 GCC 和 Clang 中编译这样的代码?

#include <cstdio>
int main() {
    __uint128_t a = 4000000000000000000;
    a *= 100;
    __uint128_t res = reinterpret_cast<__uint128_t>(reinterpret_cast<void*>(a));
    printf("%d", a == res);
}

我得到的结果是“0”,表示有数据丢失。

编辑

我认为有 3 种可能的变体。编译器错误、滥用规范或规范的后果。这是哪个?

回答

这里解释了https://en.cppreference.com/w/cpp/language/reinterpret_cast

  1. 指针可以转换为任何足够大的整数类型以保存其类型的所有值(例如到 std::uintptr_t)

这就是为什么你在第一种情况下有错误

  1. 任何整数或枚举类型的值都可以转换为指针类型...

这就是为什么您没有错误的原因,但在第二种情况下它会换行为 0。它以某种方式假设指针类型与任何整数类型相比具有最大的范围,而对于 128 位整数,情况并非如此。

请注意,一般来说 128 位整数不是整数类型,但至少 gcc 将其定义为 gcc 扩展中的:

来自https://quuxplusone.github.io/blog/2019/02/28/is-int128-integral/

libstdc++(在标准的非 gnu++XX 模式下)将 is_integral_v<__int128> 保留为 false。从库实现者的角度来看,这在一定程度上是有意义的,因为 __int128 不是标准的整数类型之一,而且,如果你称它为整数,那么你必须面对 intmax_t(它是 64 位的)每个重要的 ABI)都在说谎是“最大值”。

在 -std=gnu++XX 模式下,libstdc++ 使 is_integral_v<__int128> 变为 true

  • @CPPCPPCPPCPPCPPCPPCPPCPPCPPCPP Spec says any integer can be converted to a pointer, so it's a consequence of the spec.
  • Actually this part looks like a solution:
    (the round-trip conversion in the opposite direction is not guaranteed; the same pointer may have multiple integer representations)
    Which is a little bit confusing, I think it is a correct opinion that compiler devs assume that pointer type is the biggest.

以上是__uint128_t的reinterpret_cast的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>