Using bitwise operators

What is the purpose of the parenthetical constants in these definitions?

#define DIP_ADDRESS (0x4 << 3 | 0x0)
#define LED_ADDRESS (0x4 << 3 | 0x7)

To bitwise OR something with 0x0 seems odd. Likewise, why shift 0x4 three bits to the left (0x20) instead of using 0x20? I can only assume that 0x4 is “register 4,” but it has to be shifted up 3 bits in the address? I guess I’m asking, if these are constants, why not just use the actual constant?

DQ

To bitwise OR something with 0x0 seems odd.

Yes it is and totally ineffective.

Likewise, why shift 0x4 three bits to the left (0x20) instead of using 0x20?

No reason at all, it would make more sense shifting 0x01 five bits to the right, then you know you have put a 1 in bit 5

Dr_Quark:
What is the purpose of the parenthetical constants in these definitions?

#define DIP_ADDRESS (0x4 << 3 | 0x0)
#define LED_ADDRESS (0x4 << 3 | 0x7)

To bitwise OR something with 0x0 seems odd. Likewise, why shift 0x4 three bits to the left (0x20) instead of using 0x20? I can only assume that 0x4 is “register 4,” but it has to be shifted up 3 bits in the address? I guess I’m asking, if these are constants, why not just use the actual constant?

DQ

Some people use it as a way of documenting each of the ‘fields’ compromising the bitfield. In that example, it looks like the bottom 3 bits are used for identification (DIP is 0, LED is 7), and the address is shifted left 3 bits. So (0x4 << 3 | 0x0) is a mnenomic for saying the address is 4, and type is 0 (DIP). When you are dealing with a few of these, it makes it easier to read, if you fully fill in all fields.

Pardon, but I'm still very curious about this programming construct. I don't see the point. Please explain. DQ

Dr_Quark: Pardon, but I'm still very curious about this programming construct. I don't see the point. Please explain. DQ

What programming construct in particular? Several different things were covered.

#define DIP_ADDRESS (0x4 << 3 | 0x0)
#define LED_ADDRESS (0x4 << 3 | 0x7)

I’m interested in how the addresses inside the parentheses are parsed. My order of precedence would be:

  1. shift hex 4 left 3 bits, eg, hex 08, 10, 20, the OR hex 20 with hex 0, which is still hex 20
  2. shift hex 4 left 3 bits, eg, hex 08, 10, 20 and then OR it with hex 07, with a result of hex 27

These are constants. Why not just use 20 and 27 (hex)? If this is just an around-your-elbow of making the port number part of the address, why not put that in a comment?
DQ

Everybody has a different style of making these things up. Ultimately in the end, the compiler folds them all together and they are a single number.

Usually, you have helper macros that might build parts:

#define ADDR_COMBO(FIELD1, FIELD2) (((FIELD1) << 3) | (FIELD2))
#define DIP_ADDRESS ADDR_COMBO (0x4, 0)
#define LED_ADDRESS ADDR_COMBO (0x4, 7)

Even if you don’t, it is helpful (to some of us) when doing fields like this to group things together logically. It doesn’t matter at all to the compiler. What it matters is to humans that are reading the code. I find it much more convenient to group things by field, so that I know the first field is 0x4 and the second field is 0 or 7. If the field size was 4 bits for hex numbers or 3 bits for octal numbers, then it I can just look at the hex/octal digit. But if it is grouped this way, I don’t have to mentally shift the bits, I let the compiler constant folder do it. But if you find it more convenient to write it as 0x20, by all means do so. You could just as easily write it as 32 or 040 or 0b100000, since it is the same value in the end.

If the value is already folded, and I glance at the constant, I have to mentally do the transformation.

As to why keep in the OR of 0, I like to keep all of these fields lined up in columns. So for example, if there were 3 fields, instead of 2, I might write:

#define FRED_ADDRESS      ((0x1 << 6) | (0x0 << 3) | (0x7))
#define BARNEY_ADDRESS ((0x2 << 6) | (0x1 << 3) | (0x0))
#define WILMA_ADDRESS   ((0x0 << 6) | (0x7 << 3) | (0x1))
#define BETTY_ADDRESS    ((0x7 << 6) | (0x4 << 3) | (0x2))