首页 > 解决方案 > 重新解释 __uint128_t

问题描述

据我所知, 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 种可能的变体。编译器错误、规范滥用或规范后果。这是哪一个?

标签: c++gccclang

解决方案


这里解释了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)都在谎称自己是“最大值”。</p>

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


推荐阅读