spin_round_22
spin_round_22

Reputation: 89

Bit shift vs bit shift + and masking

I cannot see the difference between y and y2

uint16_t x = 0x0F1F2;
uint8_t y = (x & 0xFF00) >> 8;
uint8_t y2 = x >> 8;
printf("%x,", y);
printf("%x,", y2);

But I see the style with a mask often. Is there ever any reason to mask with & before doing this operation?

Upvotes: 1

Views: 4256

Answers (2)

vgru
vgru

Reputation: 51204

In this case the mask isn't needed. There are cases when you want to mask bits, but there is no sense in masking bits that are going to be shifted away. As long as you're using unsigned for bitwise operations, you're fine.

But since we're mentioning unsigned, keep in mind that all types smaller than int will be promoted to int for bitwise and arithmetic operations, and signed int kinda sucks. Left shifting a signed int which would lead to an overflow is undefined behavior. Right shifting will usually be implemented as an aritmetic shift (implementation dependant -- but usually it will repeat the sign bit when right-shifting), and this can surprise people at times:

uint16_t x = 0xF123;
uint32_t y = (x << 16) >> 16;   // implementation-dependant, but likely 0xFFFFF123 
uint32_t z = (x << 28);         // undefined behavior

Upvotes: 1

David G.
David G.

Reputation: 690

Typically you might mask before if some bits represent an integer stored in the value. This would probably be a hardware or network interface. So you might have the bit mask of 0xff00 defined, and a shift count, so you mask first then shift.

As for your example, y and y2 are the same, and if you compile and optimize (possibly in separate compilations), the code generated should be the same. (And will almost certainly not contain a shift operation, as it just needs to read the right byte.)

Upvotes: 2

Related Questions