我正在寻找一种快速将uint32_t
转换为int32_t
的方法。我可以假设所有数字都小于2 ^ 31-1,并且不需要担心代码中此时的溢出。我可以假设int32_t
的符号位是uint32_t
的最大位数吗?在编码方面,我可以将指向uint32_t
值的指针视为指向int32_t
值的指针:以下代码是否与平台无关的C代码有效并且最后一个语句是否为真? (在我的Mac上和Linux上的intel编译器都是如此)
uint32_t ui = 3;
int32_t *i = &ui;
(int32_t)ui == *i;
答案 0 :(得分:3)
如果你想要快速,并且你不关心溢出,你根本不需要做任何奇特的事情。如果你只是写
i = ui;
任何理智的编译器最多会发出一个赋值指令,尽管它可能会警告你类型不匹配和溢出的可能性。如果你写
i = (int32_t)ui;
任何理智的编译器都会发出完全相同的赋值指令,并且会吞下它对类型不匹配的怀疑(即不警告你)。
没有必要涉及指针别名或类型惩罚 - 这只会使代码混淆,并可能使其不太可靠或效率低下。
如果你担心转换,以及标志位的位置,你真的不必:
在二进制补码算法中,不需要转换,除非它检测溢出并抛出异常。在一个补码和符号幅度中,除非检测到溢出并抛出异常,否则不需要转换。
虽然不做出与机器相关的假设是明智的,但出于所有意图和目的,您可以假设您的代码将在双补码机器上运行。 (他们非常普遍。)
即使需要进行转换,无论如何都不会明显慢于直接分配。
通过在C中编写一个简单的赋值(与某些指针旋转相反),您可以确保即使某些转换需要,编译器也会处理它。
答案 1 :(得分:1)
不,这不是平台无关的C代码。 C标准不需要定义int32_t
也不需要uint32_t
。
我怀疑你实际上并不关心所有实现的平台无关C代码,我怀疑你只关心可以在你关心的平台上运行的C代码,但我不知道你在哪个实现关心。
假设存在int32_t
和uint32_t
:
使用指针转换来访问无符号类型,就好像它是相应的带符号类型一样,反之亦然,是有效的。 int32_t
是与uint32_t
对应的签名类型。正如@rici指出的那样,在实践中不仅如此,这是一项艰难的要求。
与此同时,这是不必要的复杂。在当前常用的平台上,从uint32_t
到int32_t
的简单直接转换,反之亦然,没有任何指针技巧,在运行时将需要零指令并完全按照您的预期行事