I think my question boils down to:
Why are char
and unsigned Char
treated differently even on bit operations?
They have the same size and look the same
found this but for me it does not explain why it should operate differently on bit operation level
I read two bytes from a file.
These have to be be combined into a 16 bit
number.
I do this with bit shifting <<
and logical or |
.
uint16_t universe = (hb << 8) | lb;
I thought the code worked fine but sometimes I got weirdly high numbers. 65535
instead of 511
.
It is only happening if lb
is bigger then 0x80
but the size of hb
doesn't matter.
So why is 0x70 == '\x70'
but 0x80 != '\x80'
(in some cases)
While writing the question I found that signed char
and char
are treated differently if they are >= 0x80
. (see example below)
Can somebody explain why this is and why it is even happening while doing bit wise operations?
And why doesn't it matter with hb
I think the examples explain ist best
#include <string>
using namespace std;
int main()
{
//different
uint8_t hb = 0x01;
uint8_t lb = 0xff;
uint16_t universe = (hb << 8) | lb;
cout<<universe << endl; //511
string line = string("\x01\xff");
universe = (line[0] << 8) | line[1];
cout<<universe << endl; //65535
//different
hb = 0x10;
lb = 0x80;
universe = (hb << 8) | lb;
cout<<universe << endl; //4224
line = string("\x10\x80");
universe = (line.at(0) << 8) | line.at(1);
cout<<universe << endl; //65408
universe = ('\x10' << 8) | '\x80';
cout<<universe << endl; //65408 too
//this is fine
hb = 0x83;
lb = 0x70;
universe = (hb << 8) | lb;
cout<<universe << endl; //33648
line = string("\x83\x70");
universe = (line[0] << 8) | line[1];
cout<<universe << endl; //33648
//so it is only happening if lower byte is > 0x80
if(0x70 == '\x70')
cout << "same 0x70" << endl; //same
unsigned char nn = '\x80';
if(0x80 == nn)
cout << "now its same 0x80 again " << endl; //same
uint8_t n = '\x80';
if(0x80 == n)
cout << "now its same 0x80 again " << endl; //same
if(0x80 == '\x80')
cout << "not same 0x80" << endl; //actually not the same ??
if(nn == '\x80')
cout << "not same 0x80" << endl; //actually not the same ??
char nnn = '\x80';
if(nnn == '\x80')
cout << "same 0x80" << endl; //same I THINK THIS IS THE DIFFERENCE
out << sizeof(nn) << sizeof(n) << sizeof(lb)<< sizeof(lb)<<endl; //1 1 1 1
//AND WHY IS THIS WORKING ? here is a value > 0x80 used but its working fine
hb = 0x90;
lb = 0x70;
universe = (hb << 8) | lb;
cout<<universe << endl; //36976
line = string("\x90\x70");
universe = (line[0] << 8) | line[1];
cout<<universe << endl; //36976
return 0;
}
I fixed it in my code by doing assigning the chars to a uint8_t
. But I don't understand why it's happening. Why are char
and unsigned Char
treaded differently on bit operations?
string line = string("\x01\xff");
uint8_t hb = line[0];
uint8_t lb = line[1];
universe = (hb << 8) | lb;
cout<<universe << endl; //511 like expected