代码之家  ›  专栏  ›  技术社区  ›  IInspectable

重新解释强制转换是否可以更改对象表示?

  •  9
  • IInspectable  · 技术社区  · 6 年前

    我的心理模型 reinterpret_cast 一直以来,将表达式的位序列视为不同的类型,并且 cppreference (注:这不是C++标准的一个引文)似乎同意:

    不像 static_cast ,但就像 const_cast ,和 重新解释演员 表达式不编译为任何CPU指令。它纯粹是一个编译器指令,指示编译器处理 表达 好像它是那种 新的_类型 .

    为了寻找担保,我无意中发现 [expr.reinterpret.cast] :

    [ 注意 :由执行的映射 reinterpret_­cast 可能产生,也可能不产生与原始值不同的表示。 尾注 ]

    这让我疑惑:在什么条件下 重新解释演员 生成一个对象表示不同于原始值的值?

    2 回复  |  直到 6 年前
        1
  •  9
  •   geza    6 年前

    下面是一个例子:如果您阅读 4th 要点:

    指针可以显式转换为任何整数类型,其大小足以容纳其类型的所有值。映射函数是实现定义的。[注:对于那些知道底层机器的寻址结构的人来说,这并不奇怪。尾注]

    现在,它是实现定义的,什么值 i 将会有:

    void *ptr = <some valid pointer value>;
    uintptr_t i = reinterpret_cast<uintptr_t>(ptr);
    

    它可以是任何东西,只要 reinterpret_cast 惯性导航与制导 回来我们会得到 ptr .

    代表 ptr公司 可能有所不同。标准只是说 应该“毫不奇怪”。即使,如果我们 重新解释演员 ptr公司 到更宽的整数(例如,如果指针是32位的,则强制转换为 unsigned long long int ),表示 必须 不同,因为变量的大小不同。

    所以我认为cppreference的描述有误导性,因为 重新解释演员 s、 它实际上需要CPU指令。


    Here 是另一个案例(由IInspectable发现),Keith Thompson评论道:

    Cray向量机的C编译器,比如T90,做了类似的事情。硬件地址是8字节,指向8字节的单词。void*和char*在软件中处理,并在单词中增加3位偏移量——但是由于实际上没有64位地址空间,所以偏移量存储在64位单词的高阶3位中。所以 char*和int*大小相同,但有不同的内部表示 --假设指针是“真正的”整数的代码可能会严重失败。

    char * int * 对Cray T90有不同的表述,因此:

    int *i = <some int pointer value>;
    char *c = reinterpret_cast<char *>(i);
    

    在这里, c 在crayt90上有不同的表示(并且执行此转换肯定使用CPU指令)。

    (我已经验证了,第3.1.2.7.1章 Cray C/C++ Reference Manual SR–2179 2.0 )

        2
  •  -3
  •   SoronelHaetir    6 年前

    重新解释强制转换不会更改位值,但这并不意味着结果值不会更改,这是正确的。

    一个简单的例子是将32位整数类型转换为char[4],每个元素表示一个IPv4地址的八位字节。