Search code examples
c++stringstreamistream-iterator

istream_iterator behaviour on 0x9-0xD


I have written a small test file to make the question clear :

#include <iostream>
#include <iterator>
#include <algorithm>
#include <cstdio>
#include <sstream>

void printChar(const char c) {

        std::string s(&c);
        std::istringstream iss(s);

        std::ostringstream oss;

        std::copy(std::istream_iterator<char>(iss),
                  std::istream_iterator<char>(), // reads till the end 
                  std::ostream_iterator<char>(oss));

        std::string output = oss.str();
        printf("%#x - %#x\n", c, output.c_str()[0]);
}

int main (const int argc, const char** argv) {

        for (char i = 0; i < 0x20; ++i) {
                printChar(i);
        }
        return 0;
}

Now, the expected output is going to be

 0 - 0
 0x1 - 0x1
 0x2 - 0x2
 ...
 0x1e - 0x1e
 0x1f - 0x1f

However, I get the following output for 0x9-0xD :

0x8 - 0x8
0x9 - 0x7f
0xa - 0x7f
0xb - 0x7f
0xc - 0x7f
0xd - 0x7f
0xe - 0xe

Can anyone explain why I get this result ?


Solution

  • If you fix the issue already mentioned (with the std::string constructor) and you will get

    0x8 - 0x8
    0x9 - 0
    0xa - 0
    0xb - 0
    0xc - 0
    0xd - 0
    0xe - 0xe
    

    This is still undefined behaviour because you are dereferencing output when it is empty. The reason that it is empty is that streams ignore whitespace - they are considered as delimiters.

    Changing your printf to

    printf("%#x - %#x\n", c, !output.empty() ? output.c_str()[0] : -1);
    

    gives

    0x8 - 0x8
    0x9 - 0xffffffff
    0xa - 0xffffffff
    0xb - 0xffffffff
    0xc - 0xffffffff
    0xd - 0xffffffff
    0xe - 0xe