0

I need to get 2 high bits from one byte in array. I have enum, that defines all values of those 2 bits:

...
enum elems{
    elem1 = 0,
    elem2 = 1,
    elem3 = 2,
    elem4 = 3
}
...
elems getElems(const QByteArray &data)
{
    return (elems)(data[3] >> 6);
}
...
qDebug() << (data[3] >> 6); // return 0 or 1 or 2 or 3 (true way)
qDebug() << getElems(data); // return 0 or 1 or -1 or -2 (wrong way)
...

When data[3] == 0 it return 0, when data[3] == 64 it return 1, but when data[3] == 192 it return -1 and when data[3] == 128 it return -2.

Why it's happens?

murzagurskiy
  • 1,273
  • 1
  • 20
  • 44

2 Answers2

2

QByteArray is an array to char, which most probably is signed. Therefore 192 is outside char's range and wraps back to -64

When you return (elems)(data[3] >> 6) it will do an arithmetic shift like most compiler implementations on a signed type (because right shift in C++ is implementation defined). That will propagate the sign bit (1 in this case because of -64) to the left, making all the bits in the byte 1 and is the reason why you see -1 returned.

If you only want the 2 high bits, mask the result before returning

return (elems)((data[3] >> 6) & 0x03);

Or cast the type to unsigned

return (elems)((qint8)data[3] >> 6);

Alternatively this will also work

return (elems)((data[3] >> 6) & 0xFF);
phuclv
  • 37,963
  • 15
  • 156
  • 475
1

Lưu Vĩnh Phúc is correct. you can also modify your function as:

return (elems)((unsigned char)data[3] >> 6);
Afshin
  • 392
  • 2
  • 11
  • it's correct. Right shift on unsigned type is always logical shift. Only shifts on signed type may be arithmetic – phuclv Mar 17 '16 at 16:22