# Thread: Bit fields and hex

1. ## Bit fields and hex

Hello!

When studying OpenGL, I noticed that constants are defined as such:

Code:
```#define GL_CONSTANT_1 0x01 // 1 = 00000001
#define GL_CONSTANT_2 0x02 // 2 = 00000010
#define GL_CONSTANT_3 0x04 // 4 = 00000100```
I also read about bit fields, and, if I have understood them correctly, they work like this:

Code:
```typedef struct
{
unsigned char one : 1;
unsigned char two : 1;
// ...
unsigned char eight : 1;
} BitField;```
So, if you want to store eight boolean numbers in just one byte, you can do that with a bit field. (Please correct me if I've misunderstood.)

However, what's the point in using hex when defining? Is there any difference between writing:
Code:
```#define CONSTANT 0x01
// ... and ...
#define CONSTANT 1```
I understand that it might be easier when the person reading it is internally converting it to binary, but what is (and I assume this exists) the reason(s) beyond that?

I'd appreciate any help on this matter.

2. Hex translates into decimal fine.

It's just a way of assigning a value that humans can easily deconstruct into a binary string.

Also, if you want 8 boolean numbers in one byte just use a char set a specific value.

To set a bit,
Code:
`unsigned i |= (1 << bit);`
To reset a bit,
Code:
`unsigned i &= ~(1 << bit);`
You can just use the & operator to see if a particular bit is set.

3. I'm personally not too keen on bit fields myself - I prefer packing information into a standard (unsigned) data type and using bitwise operators.

Is there any difference between writing:

Code:
```#define CONSTANT 0x01
// ... and ...
#define CONSTANT 1```
You might not see much of a difference there, since the numerical representations of decimal and hex are basically identical for values from zero to nine . But what about:

Code:
```#define CONSTANT 0x1D
// ... and ...
#define CONSTANT 29```
It comes down to context. If you're using the values as actual numbers (such as defining the maximum size of an array), you'll want them to be in a decimal representation so that it's easy for you, the programmer, to easily understand the quantity.

Hex values can be defined instead for several reasons. One is that, since it's a shorthand for binary, it's easier to define hex values used for masking.

Code:
```#define ENABLE_MOTOR_1 0x08 // binary: 0000 1000
#define ENABLE_MOTOR_2 0x02 // binary: 0000 0010

// ...

unsigned char control = 0x00;

control |= ENABLE_MOTOR_1;     // control = 0x08, motor 1 on

control |= ENABLE_MOTOR_2;     // control = 0x0A, motor 1 and motor 2 on

control &= ~(ENABLE_MOTOR_1);  // control = 0x02, motor 2 on```

4. So, if I've understood it correctly, it can be used as follows:
Code:
```// Base.h
#define ENABLE_LIGHT 0x01   // 0000 0001
#define ENABLE_ENGINE 0x02 // 0000 0010

// Main.c
unsigned char settings = 0x00;
if (settings & (1 << CONSTANT_1)) { /* turn light on */ }
if (settings & (1 << CONSTANT_2)) { /* turn engine on */ }```

5. Something like that, though I wouldn't use the bit shifts like that when you're defining specific hex values.

I suggest you replace the "turn light on" and "turn engine on" comments with print messages and make a simple program that you can run and play with.

6. I would set settings to something non-zero but yeah, that's the gist of it.

7. In that case, how would you enable, disable, toggle and check if a bit is enabled?

I use this code:
Code:
```#define EnableBit(var, pos) ((var) |= (1 << (pos - 1)))
#define IsBitEnabled(var, pos) ((var) & (1 << (pos - 1)))

int main()
{
EnableBit(settings, 2);
printf("%d", IsBitEnabled(settings, 2));
}```
But it shows "2" rather than "1" (it outputs the value of "settings" rather than true or false), which I had expected... What am I doing wrong?

8. Originally Posted by MeNeedsHelp
In that case, how would you enable, disable, toggle and check if a bit is enabled?
You should in all honesty just google this.

9. I assume you missed my edit, since it wasn't in the quote. My question was (initially, at least) poorly phrased.

10. I think 1 << (2 - 1) is equal to 2. Assuming var == 0, then you have 0010 which is 2. To get 1, use 1 << 0.

Treat the bit position like you would with 2 ^ position. 1 == 2 ^ 0.

11. It doesn't seem that strange when you work it out.

Code:
```EnableBit(settings, 2);

/* settings = 0x02; */

IsBitEnabled(settings, 2)

/*
settings & (1 << (pos - 1))
settings & (1 << (2-1))
settings & (1 << 1)
settings & 2
0x02 & 0x02 = 0x02 = 2
*/```
Recall though, in C, true is not necessarily one - it's just non-zero. So if you used that macro in an "if()", it would work as expected.

If you specifically wanted a 1 for true, you could always do something cute like:

Code:
`#define IsBitEnabled(var, pos) (!!((var) & (1 << (pos - 1))))`

12. OK...

Code:
```// Base.h
#define LIGHT_ENABLED 0x01
#define ENGINE_ENABLED 0x02
#define AC_ENABLED 0x08

#define EnableBit(var, pos) ((var) |= (1 << (pos - 1)))

// Main.c

EnableBit(settings, AC_ENABLED);```
"AC_ENABLED" equals eight, thus "EnableBit(settings, AC_ENABLED)" equals "var |= (1 << 8)" sets bit #8 rather than bit number four. How can I fix this apart from changing "RADIO_ENABLED" to 0x03 and "AC_ENABLED" to 0x04 (in which case, why would I even use hex?)?

13. Why would you shift a bit 8 times when you really wanted to shift it only 4?

14. 0x01 = 0000 0001
0x02 = 0000 0010
0x04 = 0000 0100

However,
0x03 = 0000 0011

If I just want to switch the bit four times, I would just set "RADIO_ENABLED" to 3 rather than 0x03. If I do it as shown above, I don't see any point in using hex.

Sorry if I'm not making any sense here.

15. Originally Posted by MeNeedsHelp
0x01 = 0000 0001
0x02 = 0000 0010
0x04 = 0000 0100

However,
0x03 = 0000 0011
Indeed. Now consider a nibble of a byte in full:
0x00 = 0000 0000
0x01 = 0000 0001
0x02 = 0000 0010
0x04 = 0000 0100
0x05 = 0000 0101
0x06 = 0000 0110
0x07 = 0000 0111
0x08 = 0000 1000
0x09 = 0000 1001
0x0a = 0000 1010
0x0b = 0000 1011
0x0c = 0000 1100
0x0d = 0000 1101
0x0e = 0000 1110
0x0f = 0000 1111

Clearly, after the "0x" prefix, the "0" corresponds to one nibble and the other hex digit corresponds to the other nibble. If you are working with bitwise operations and have a mental map of hex digits to the corresponding nibble, you will be able to mentally identify the bits of any particular nibble more easily than if you were presented with the number in decimal representation (at least once the number is larger than 16).