是将int32强制转换为uint32吗?

时间:2020-01-05 14:04:04

标签: c++ casting type-conversion int

我希望将int32_t的位粘贴到类型uint32_t中,而无需进行任何转换,而只是重新解释。以下代码正是我想要的:

int32_t  iA = -1;
uint32_t uA = *(uint32_t*)&iA;

但是我想知道,我是否可以依靠下面的代码来更容易地编写强制转换,以生成相同(或更少)的程序集,最好是mov? (即,它将永远不会对其进行“数学运算”,而使基础位保持不变。)

int32_t  iB = -1;
uint32_t uB = (uint32_t)iB;

assert(uA == uB); // ?

2 个答案:

答案 0 :(得分:7)

直到C ++ 20,带符号整数的表示形式是实现定义的。但是,std::intX_torder,即使在C ++ 20之前也具有2'补码表示:

int8_tint16_tint32_tint64_t-有符号整数类型,宽度分别精确地为8、16、32和64位,没有填充位,并使用2负值的补码(仅在实现直接支持类型时才提供)

写作时

std::int32_t  iA = -1;
std::uint32_t uA = *(std::uint32_t*)&iA;

您将获得设置了所有位的值。如果“类型类似于...类型是与...的动态类型相对应的有符号或无符号类型,则允许通过类型std::int32_t的指针访问std::uint32_t*的标准guaranteed物体”。因此,严格来说,在取消引用指针之前,我们必须确保std::uint32_t确实是与std::int32_t对应的无符号类型:

static_assert(std::is_same_v<std::make_unsigned_t<std::int32_t>, std::uint32_t>);

写作时

std::int32_t  iB = -1;
std::uint32_t uB = (std::uint32_t)iB;

您依靠转换为says的无符号类型并保证产生相同的值。

至于组装,两个演员都是无人操作:

std::uint32_t foo() {
    std::int32_t  iA = -1;
    static_assert(std::is_same_v<std::make_unsigned_t<std::int32_t>, std::uint32_t>);
    return *(std::uint32_t*)&iA;
}

std::uint32_t bar() {
    std::int32_t  iB = -1;
    return (std::uint32_t)iB;
}

well-defined

foo():
        mov     eax, -1
        ret
bar():
        mov     eax, -1
        ret

答案 1 :(得分:3)

使用memcpy是避免别名类型时出现未定义行为的常见解决方案。 在评论中指出,仅在签名上有所不同的别名类型是可以的,但是对于floatint来说不是这种情况。

memcpy只要对象表示形式对该类型有效即可。

编译器非常擅长优化memcpy调用,在本例中为the call is completely optimized away

相关问题