I know all about bit shift operators, for example, left shift means multiply by powers of 2. However, I'm still wondering what that purpose serves for example, I've seen conditional statements that left shift by 32. So why do that?
If I am reconstructing an integer from 2 bytes sent by an external device, I use a shift left 8 bits to get the high byte into position in the integer.
I know all about bit shift operators, for example, left shift means multiply by powers of 2. However, I’m still wondering what that purpose serves for example, I’ve seen conditional statements that left shift by 32. So why do that?
bit shifting is really a division or multiply by 2.
x = x >> 1; really means
x = x / 2; the same way that
x = x << 1; really means
x = x * 2. the reason why bit shifting operations exist is because from a binary point of view (ie: within the CPU itself) they are very simple operations to occur. back in the old days when there was not a fast multiply or divide instruction provided by the CPU - you could even use multiple shifts to do the same:
ofs = (y * 320) + x; could be written as
ofs = ( y << 8 ) + ( y << 5 ) + x; as it really meant
ofs = (y * 256) + (y * 64) + x. it would be much faster to do this over using a lot of resources in the CPU with a multiply or divide.
As long as you don't do it at the dinner table, it does no harm.
However, I'm still wondering what that purpose serves for example, I've seen conditional statements that left shift by 32. So why do that?
Without seeing the particular example, we can only guess, but maybe it involved a 64 bit variable.
It’s also very useful if you want to pack some data to transmit them over Serial, or if you are running out of memory…
For example if I want to send 2 values 0xA and 0xB, I just pack them into a single byte 0xAB, and unpack it on the other device. I believe this is the basis of almost every networking code, in videogames for example.
Another practical example of packing:
int Team = 1; int Player = 2; int Weapon = 7; irsend.sendSony( ( Team << 8 | Player << 4 | Weapon ), 12);
If you are not working a the bit-level and otherwise manipulating bits, you probably don't need to bit-shift. It's just one of the bitwise operations when you need to read, write, or flip bits.
Usually, bit manipulation is hardware related.. If you want to read a switch or write to an LED, you nay need to deal with one bit in a byte. The Arduino language library allows you to read/write individual I/O pins, so bitwise operations are not needed as much as with other microprocessors/microcontrollers where you are reading/writing an 8-bit or 16-bit I/O port.
When you are working in binary, the variable usually represents a "bit pattern", instead of a "number". That is, each bit may indicate the status of something... It's a number to the computer, but maybe bit 0 is a "status OK" LED, and bit 1 is a "relay on" LED, etc. Of course, in that case, you probably wouldn't want to bit-shift but you might want to do some individual bit-writes.
If you are working at the bit-level, you'll normally use hexadecimal in your program, instead of decimal so you can more easily visualize what's going on. With a little memorization, you can learn to convert between hex and binary values of any size in your head. (Converting between decimal and binary is not so easy!) The microcontroller doesn't care if you use decimal, hex, octal, or binary... It's all converted to binary by the compiler... It just makes it easier for you, the programmer.
I don't do it to multiply or divide by two, I do it when I want to bit-shift. ;) I've used bit-shifting to "bang-out" serial data, and and for sequencing lighting effects. Sometimes with lighting effects, I'm actually rotating bits (i.e. If you right-shift, instead of throwing-away the right-most bit you save it and write it back into the left-most bit.)