Understanding Bitwise Operators



> I’m currently learning C (cliche’ entry?) and I am finding bitwise
> operations a tad challenging.  I have a sound understanding of how
> boolean logic works (i think), but I find it hard to evaluate the
> constructs when I see them in code.

> For example, in a network program, a port number is subjected to the
> following operation:

> port = (port & 0xff) << 8 | port >>8;

Assuming that port is a 16-bit unsigned integer, containing two 8-bit
bytes,
this code swaps the two bytes. For example, 0xABCD would be converted to
0xCDAB.

> AFAIK, port is being assigned the outcome of :

> 1) An AND operation to ensure that the variable ‘port’ is not greater
> than 255.

0xff is an 8-bit mask. (port & 0xff) is “grabbing” the right-most byte
of
port.

> 2) A left shift by 8 bits (not too sure why though)

The result is shifted left 8 bits, filling the right-most byte with
zeros.

> 3) An OR with the outcome of a right shift by 8 bits (again, not too
> sure why).

(port >> 8) shifts port right 8 bits, filling the left-most byte with
zeros.
The result is OR’d with the previously left-shifted right-most byte of
port.
In other words, the left byte is swapped with the right byte, probably
to
compensate for endianess.

On a system where CHAR_BIT is 8 and port is a 2 byte integer, this
code will swap the bytes, probably as part of some off-topic
network-to-host or host-to-network byte order conversion.

Imagine that ‘port’ is something like this:

[10101010][11111111]

1. port & 0xff zeroes the most significant byte.

[00000000][11111111]

2. The 8 bit left-shift will put the least significant byte where
the most significant byte used to be.  The least significant byte
is now filled with zeroes.

[11111111][00000000]

3. The 8 bit right-shift, puts the original most significant byte
into the least significant byte position.  The most significant byte
is filled with zeroes.

[00000000][10101010]

4. The OR operation combines the two bytes.

[11111111][10101010]

Even if sizeof port > 2 (still assuming CHAR_BIT==8), this will swap
the two low-order bytes of the value of port as long as the initial
value is no greater than 65535.  Without assuming CHAR_BIT==8, you can
still say that it swaps the two low-order octets, which may or may not
be “bytes” in the C sense of the word.

If port >= 65536 (i.e., if there are non-zero bits beyond the
low-order 16 bits), other things will happen.  If that’s going to be
an issue, you might consider preceding the above with
port &= 0xffff;

This all assumes that port is of an unsigned type.  If it’s signed,
there are rules for the behavior of bitwise operations, but I’m too
lazy to look them up.

BTW, I probably would have written this as

port = ((port & 0xff) << 8) | (port >> 8);

It’s equivalent, but I had to check the standard to make sure that
“<<” and “>>” bind more tightly than “|”.

Understanding Bitwise Operators


Leave a Comment

You must be logged in to post a comment.