Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Bug in std::from_chars when type is int8_t and base=2

std::from_chars fails with a generic error when parsing a string of bits (base=2) as a signed 8-bit integer, whereas std::stoi parses the signed 8-bit integer without error.

Both blocks in the program below parse the same string of bits. The program ends by calling std::abort on the first assertion in the second block. std::stoi parses the same string of bits without error.

// 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);
    }
}

Output of running this program after compiling with g++ -std=c++17 -O0 -g main.cc -o main.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

# ./main
main: main.cc:24: int main(): Assertion `ec == std::errc()' failed.
Aborted

>Solution :

10011100 in binary is 156 in decimal.

A signed 8-bit integer type is not able to hold that value (maximum is 127) and therefore std::from_chars will fail.

It doesn’t fail for std::stoi, because the value 156 is in range of int (which is at least 16bit wide).


If your intention is to interpret the bits as a two’s complement representation of an 8bit integer value, then you need to first parse it into a uint8_t, then cast to int8_t, assuming that the C++ implementation also uses two’s complement to represent int8_t. This is mandatory in C++20, but not C++17. If the implementation does not use the same representation as what you want to parse represents, then you need to do the conversion manually.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading