Here I have a function that takes a byte, swaps its halves and returns the result:
unsigned char swap_bits(unsigned char octet)
{
return ((octet >> 4) | (octet << 4));
}
The achieved effect would be as follows:
1 byte
_____________
0100 | 0001
\ /
/ \
0001 | 0100
Does the Single Pipe |
serve as a bitwise OR operator here? How does it collaborate/work with the Shift Operators <<
and >>
in this case? Can I replace it with a logical OR operator ||
or anything else? Thanks!
Edit: This is my first question on StackOverflow and I received many great answers within a short time. I do appreciate all of them!
CodePudding user response:
Yes, it's the bitwise OR operator. That's the only meaning of the |
operator in C.
The left and right shift operators move each 4-bit half of the byte (AKA "nibble") to the opposite half. If you start with
0100 | 0001
then octet << 4
results in
0001 | 0000
and octet >> 4
results in
0000 | 0100
Notice that 0000
gets shifted into the other nibble when you do each of these shifts. So when you OR everything together, you just get both shifted nibbles.
CodePudding user response:
Does the Single Pipe | serve as a bitwise OR operator here?
Yes, it is the bitwise OR operator in C.
How does it collaborate/work with the Shift Operators << and >> in this case?
There's quite a bit going on "between the lines" in this code.
Given some data 0xAB
, the >> 4
results in 0x0A
and the << 4
results in 0xAB0
. It's important to realize that most operators in C come with implicit integer promotion and the shifts are actually carried out on type int
.
So the |
operator get operands of type int
handed to it and 0x0A | 0xAB0
= 0xABA
.
Finally during the return, there is another implicit conversion back to unsigned char
, known as "lvalue conversion". This works just like assignment with =
, where the right operand of =
is converted to the type of the left operand. In my example this causes the 0xABA
to get truncated into 0xBA
.
This narrowing conversion can be thought as conversion "as if by modulus by 1 more than the max of what the type can hold". That is, 0xABA % (255 1) = 0xBA. Which as it happens is the same thing as discarding everything but the least significant byte.
Can I replace it with a logical OR operator || or anything else?
No. ||
evaluates its arguments to zero or non-zero and returns the integer 0
or 1
like a Boolean. Whereas bitwise |
merges the two operands together, just like binary addition. 0001b 0010b = 0011b for example. So to answer the second part of the question,
is often analogous to bitwise OR, but it's more confusing to read code using
.