std::from_chars
将位字符串 (base=2) 解析为有符号 8 位整数时,会失败并出现一般错误,而std::stoi
解析有符号 8 位整数时不会出现错误。
下面程序中的两个块都解析相同的位串。程序以调用std::abort
第二个块中的第一个断言结束。std::stoi
解析相同的位串没有错误。
// Compile: g++ -std=c++17 -O0 -g main.cc -o main
#include <string>
#include <cassert>
#include <charconv>
#include <cstdint>
int main()
{
{
std::string bits = "10011100";
int base = 2;
std::int8_t num = std::stoi(bits.c_str(), nullptr, base);
assert(num == -100);
}
{
// Bug found in std::from_chars when type is int8_t and base=2.
std::string bits = "10011100";
int base = 2;
std::int8_t num;
auto [ptr, ec] = std::from_chars(bits.data(),
bits.data() + bits.size(),
num,
base);
assert(ec == std::errc()); // Calls std::abort.
assert(num == -100);
}
}
编译后运行该程序的输出g++ -std=c++17 -O0 -g main.cc -o main
。
# ./main
main: main.cc:24: int main(): Assertion `ec == std::errc()' failed.
Aborted
10011100
二进制是156
十进制。有符号 8 位整数类型无法保存该值(最大值为
127
),因此std::from_chars
会失败。它不会失败
std::stoi
,因为该值156
在 的范围内int
(至少 16 位宽)。如果您的目的是将这些位解释为 8 位整数值的二进制补码表示,那么您需要首先将其解析为 a
uint8_t
,然后转换为int8_t
,假设 C++ 实现也使用二进制补码来表示int8_t
。这在 C++20 中是强制的,但在 C++17 中不是强制的。如果实现不使用与您要解析的表示相同的表示,那么您需要手动进行转换。