在C++中将以十六进制形式存储的负长整型字符串转换为长整型变量

3

我正在尝试将一个十六进制的stringstream转换为long类型。我来这里求助,但是他们给出的解决方案(对于short、int和大多数long类型有效)对于需要至少16个十六进制数字表示的负long类型无效。

基本上,我有一个名为hx的stringstream,其中填充了应该等于-9223372036854775808的十六进制数字。

#include <iostream>
#include <sstream>
#include <climits>

using namespace std;

int main() {
    stringstream hx;
    hx << hex << LONG_MIN;
    cout << hx.str() << '\n';

    long value;
    hx >> value;

    cout << value << '\n';
    return 0;
}

实际输出:

8000000000000000
9223372036854775807

预期输出:

8000000000000000
-9223372036854775808

当符号位为1时,我不明白为什么十六进制值会被转换成正数。

2个回答

0

这里是解决方案和其他答案中所解释的推理 hx << hex << LONG_MIN 将隐式使用 printf("%lx", ...),其类型为 unsigned long:

int main() {
    stringstream hx;
    hx <<hex << (LONG_MIN);
    cout << hx.str() << '\n';

    unsigned long value;
    hx >> value;

    cout << static_cast<long>( value ) << '\n';
    return 0;
}

你应该明确将 LONG_MIN 转换为 unsigned long,否则行为是未定义的。 - xskxzr
在两个不同的在线 C++ 编译器上检查过,看起来一致:http://cpp.sh/2thu 和 https://repl.it/repls/LankyGoodValue - PapaDiHatti
未定义行为意味着任何事情都可能发生,包括预期的行为,编译器不需要诊断它。 - xskxzr
你不觉得有符号转无符号的规则是固定的,而且不依赖于编译器吗?这意味着如果我执行 unsigned int x = -1,然后输出结果,它将始终保持一致。 - PapaDiHatti
但是没有转换... LONG_INT 作为 long 传递。 printf 不会对其参数执行转换,如果类型不匹配,则会导致未定义的行为。 - xskxzr

0

首先,hx << hex << LONG_MIN将隐式使用printf("%lx", ...)来打印该值,这导致未定义行为,因为LONG_MIN不是unsigned long类型。

其次,假设hx.str()现在存储了字符串8000000000000000。为了输入到value,它被解释为一个大的数。因此,std::numeric_limits<long>::max(),即9223372036854775807被存储在value


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接