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))