我有一个8个字符string
表示十六进制数字,我需要将其转换为int
。此转换必须保留字符串"80000000"
和更高的位模式,即这些数字应该是负数。不幸的是,天真的解决方案:
int hex_str_to_int(const string hexStr)
{
stringstream strm;
strm << hex << hexStr;
unsigned int val = 0;
strm >> val;
return static_cast<int>(val);
}
如果val > MAX_INT
(返回值为0),对我的编译器不起作用。将val的类型更改为int
也会导致较大的数字为0。我已经在SO上尝试了几种不同的解决方案,但还没有成功。
这就是我所知道的:
sizeof(int)
将在我的代码运行的每个架构上至少为4个。long
投射到int
会导致INT_MAX
当值太大时。这是非常难以正确地做到,或者至少它已经适合我。有没有人知道便携式解决方案?
更新
将static_cast
更改为reinterpret_cast
会导致编译错误。评论促使我在上面的代码中尝试C风格的演员:return (int)val
,并且它有效。 在这台机器上。在其他架构上它仍然是安全的吗?
答案 0 :(得分:10)
引用C ++ 03标准,§4.7/ 3(积分转换):
如果目标类型已签名,则该值如果可以在目标类型(和位字段宽度)中表示,则不会更改; 否则,该值是实现定义的。
因为结果是实现定义的,所以根据定义,不可能有真正的便携式解决方案。
答案 1 :(得分:8)
虽然有很多方法可以使用强制转换和转换来实现这一点,但大多数都依赖于在某些计算机/某些编译器上碰巧具有明确定义的行为的未定义行为。而不是依赖于未定义的行为,复制数据:
int signed_val;
std::memcpy (signed_val, val, sizeof(int));
return signed_val;
答案 2 :(得分:5)
您可以通过补充并添加一个来取消无符号二进制补码数。让我们为负面做这件事:
if (val < 0x80000000) // positive values need no conversion
return val;
if (val == 0x80000000) // Complement-and-addition will overflow, so special case this
return -0x80000000; // aka INT_MIN
else
return -(int)(~val + 1);
这假设您的整数用32位二进制补码表示(或具有相似范围)表示。它不依赖于与有符号整数溢出相关的任何未定义行为(注意 unsigned 整数溢出的行为是明确定义的 - 尽管这不应该发生在这里!)。
请注意,如果您的整数不是32位,事情会变得更复杂。您可能需要使用~(~0U >> 1)
而不是0x80000000
之类的内容。此外,如果您的int不是二进制补码,则某些值可能存在溢出问题(例如,在补码机器上,-0x80000000
无法用32位有符号整数表示)。然而,非二重补偿机器在今天非常罕见,所以这不太可能是一个问题。
答案 3 :(得分:4)
这是另一个对我有用的解决方案:
if (val <= INT_MAX) {
return static_cast<int>(val);
}
else {
int ret = static_cast<int>(val & ~INT_MIN);
return ret | INT_MIN;
}
如果我屏蔽掉高位,我会避免在施法时溢出。然后,我可以安全地将其恢复原状。
答案 4 :(得分:2)
C ++ 20将有std::bit_cast逐字复制位:
#include <bit>
#include <cassert>
#include <iostream>
int main()
{
int i = -42;
auto u = std::bit_cast<unsigned>(i);
// Prints 4294967254 on two's compliment platforms where int is 32 bits
std::cout << u << "\n";
auto roundtripped = std::bit_cast<int>(u);
assert(roundtripped == i);
std::cout << roundtripped << "\n"; // Prints -42
return 0;
}
cppreference显示了example,如何根据bit_cast
(在Notes中)实现自己的memcpy
。
尽管OpenVMS不太可能很快获得C ++ 20支持,但我希望这个答案可以帮助通过互联网搜索得出相同问题的人。
答案 5 :(得分:-1)
unsigned int u = ~0U;
int s = *reinterpret_cast<int*>(&u); // -1
Сontrariwise:
int s = -1;
unsigned int u = *reinterpret_cast<unsigned int*>(&s); // all ones