I was trying to understand if ispanstream
could be used extract data from a buffer.
Let's say that I have a char buffer containing a series of different variables of different types. When I extract from the stream to a variable with a size other than the one of the underlying buffer I get that the destination variable is set to 0; if instead the destination variable is of the same size of the buffer, it gets populated as I would expect.
Here a MWE:
#include <iostream>
#include <array>
#include <spanstream>
#include <cstdint>
union S
{
int32_t int32_;
uint64_t uint64_;
std::array<uint8_t, sizeof(uint64_t)> arr;
};
int main()
{
char underlyingBuf[15];
for (uint8_t i = 0; i < 15; i++)
underlyingBuf[i] = i + 100;
std::span<char, sizeof(underlyingBuf)> span{ underlyingBuf };
std::ispanstream iss(span);
S read_var{ 0LL };
for (size_t i = 0; i < sizeof(read_var.int32_); ++i)
iss >> read_var.arr[i];
//iss >> read_var.int32_;
std::cout.setf(std::cout.hex, std::cout.basefield);
std::cout.setf(std::cout.showbase);
std::cout << read_var.uint64_ << std::endl;
}
Here, the output of this code is 0x67666564, but if I uncomment the line iss >> read_var.int32_;
(or if I run only that instead of the for loop) the output is 0.
I was expecting the code to output 0x67666564 if I ran the commented line instead of the for loop, and 0x6B6A6968 if I ran it after the for loop.
ispanstream
works?span
?read_var.int32_
to 0 when calling iss >> read_var.int32_;
instead of leaving it unchanged?I'm relatively new to C++ (especially in its more modern fashions) and I struggle to understand what I got wrong.
I get the same behaviour both with msvc and gcc, so I assume this is how it's supposed to behave. Thanks!
as @some programmer dude pointed out, my MWE was a bit naughty in the way I used the union. Here a revised example:
#include <iostream>
#include <array>
#include <spanstream>
#include <cstdint>
int main()
{
char underlyingBuf[15];
for (uint8_t i = 0; i < 15; i++)
underlyingBuf[i] = i + 100;
std::span<char, sizeof(underlyingBuf)> span{ underlyingBuf };
std::ispanstream iss(span);
int8_t var1{ 0L };
int32_t var2{ 0L };
iss >> var1 >> var2;
std::cout.setf(std::cout.hex, std::cout.basefield);
std::cout.setf(std::cout.showbase);
std::cout << var1 << "\t" << var2 << std::endl;
}
In this case the output is var1 == d and var2 == 0. Why is var2 not being assigned to the content of the buffer?
The buffer contains "defghijklmnopqr".
iss >> var1 >> var2;
The type of var1
is int8_t
which is commonly signed char
. Therefore, 'd' (or 100) is read into var1
and an integer is attempted to be read from the string efghijklmnopqr
. This isn't integral, so the value of var2
isn't changed and the failbit is set: https://godbolt.org/z/ME7ozdTGY