# Bit Fields in C

In C, we can specify size (in bits) of structure and union members. The idea is to use memory efficiently when we know that the value of a field or group of fields will never exceed a limit or is withing a small range.

For example, consider the following declaration of date without use of bit fields.

 `#include ` ` `  `// A simple representation of date ` `struct` `date ` `{ ` `   ``unsigned ``int` `d; ` `   ``unsigned ``int` `m; ` `   ``unsigned ``int` `y; ` `}; ` ` `  `int` `main() ` `{ ` `   ``printf``(````"Size of date is %d bytes "````, ``sizeof``(``struct` `date)); ` `   ``struct` `date dt = {31, 12, 2014}; ` `   ``printf``(``"Date is %d/%d/%d"``, dt.d, dt.m, dt.y); ` `}`

Output:

```Size of date is 12 bytes
Date is 31/12/2014```

The above representation of ‘date’ takes 12 bytes on a compiler where an unsigned int takes 4 bytes. Since we know that the value of d is always from 1 to 31, value of m is from 1 to 12, we can optimize the space using bit fields.

 `#include ` ` `  `// A space optimized representation of date ` `struct` `date ` `{ ` `   ``// d has value between 1 and 31, so 5 bits ` `   ``// are sufficient ` `   ``unsigned ``int` `d: 5; ` ` `  `   ``// m has value between 1 and 12, so 4 bits ` `   ``// are sufficient ` `   ``unsigned ``int` `m: 4; ` ` `  `   ``unsigned ``int` `y; ` `}; ` ` `  `int` `main() ` `{ ` `   ``printf``(````"Size of date is %d bytes "````, ``sizeof``(``struct` `date)); ` `   ``struct` `date dt = {31, 12, 2014}; ` `   ``printf``(``"Date is %d/%d/%d"``, dt.d, dt.m, dt.y); ` `   ``return` `0; ` `}`

Output:

```Size of date is 8 bytes
Date is 31/12/2014```

Following are some interesting facts about bit fields in C.

1) A special unnamed bit field of size 0 is used to force alignment on next boundary. For example consider the following program.

 `#include ` ` `  `// A structure without forced alignment ` `struct` `test1 ` `{ ` `   ``unsigned ``int` `x: 5; ` `   ``unsigned ``int` `y: 8; ` `}; ` ` `  `// A structure with forced alignment ` `struct` `test2 ` `{ ` `   ``unsigned ``int` `x: 5; ` `   ``unsigned ``int``: 0; ` `   ``unsigned ``int` `y: 8; ` `}; ` ` `  `int` `main() ` `{ ` `   ``printf``(````"Size of test1 is %d bytes "````, ``sizeof``(``struct` `test1)); ` `   ``printf``(````"Size of test2 is %d bytes "````, ``sizeof``(``struct` `test2)); ` `   ``return` `0; ` `}`

Output:

```Size of test1 is 4 bytes
Size of test2 is 8 bytes```

2) We cannot have pointers to bit field members as they may not start at a byte boundary.

 `#include ` `struct` `test ` `{ ` `   ``unsigned ``int` `x: 5; ` `   ``unsigned ``int` `y: 5; ` `   ``unsigned ``int` `z; ` `}; ` `int` `main() ` `{ ` `   ``struct` `test t; ` ` `  `   ``// Uncommenting the following line will make ` `   ``// the program compile and run ` `   ``printf``(``"Address of t.x is %p"``, &t.x); ` ` `  `   ``// The below line works fine as z is not a ` `   ``// bit field member ` `   ``printf``(``"Address of t.z is %p"``, &t.z); ` `   ``return` `0; ` `}`

Output:

` error: attempt to take address of bit-field structure member 'test::x' `

3) It is implementation defined to assign an out-of-range value to a bit field member.

 `#include ` `struct` `test ` `{ ` `   ``unsigned ``int` `x: 2; ` `   ``unsigned ``int` `y: 2; ` `   ``unsigned ``int` `z: 2; ` `}; ` `int` `main() ` `{ ` `   ``struct` `test t; ` `   ``t.x = 5; ` `   ``printf``(``"%d"``, t.x); ` `   ``return` `0; ` `} `

Output:

`Implementation-Dependent`

4) In C++, we can have static members in a structure/class, but bit fields cannot be static.

 `// The below C++ program compiles and runs fine ` `struct` `test1 { ` `   ``static` `unsigned ``int` `x; ` `}; ` `int` `main() {  } ` ` `  ` `  `// But below C++ program fails in compilation as bit fields ` `// cannot be static ` `struct` `test1 { ` `   ``static` `unsigned ``int` `x: 5; ` `}; ` `int` `main() {  } ` `// error: static member 'x' cannot be a bit-field `

5) Array of bit fields is not allowed. For example, the below program fails in compilation.

 `struct` `test ` `{ ` `  ``unsigned ``int` `x: 5; ` `}; ` ` `  `int` `main() ` `{ ` ` `  `} `

Output:

`error: bit-field 'x' has invalid type`

Exercise:
Predict the output of following programs. Assume that unsigned int takes 4 bytes and long int takes 8 bytes.
1)

 `#include ` `struct` `test ` `{ ` `   ``unsigned ``int` `x; ` `   ``unsigned ``int` `y: 33; ` `   ``unsigned ``int` `z; ` `}; ` `int` `main() ` `{ ` `   ``printf``(``"%d"``, ``sizeof``(``struct` `test)); ` `   ``return` `0; ` `}`

2)

 `#include ` `struct` `test ` `{ ` `   ``unsigned ``int` `x; ` `   ``long` `int` `y: 33; ` `   ``unsigned ``int` `z; ` `}; ` `int` `main() ` `{ ` `   ``struct` `test t; ` `   ``unsigned ``int` `*ptr1 = &t.x; ` `   ``unsigned ``int` `*ptr2 = &t.z; ` `   ``printf``(``"%d"``, ptr2 - ptr1); ` `   ``return` `0; ` `} `

3)

 `union` `test ` `{ ` `  ``unsigned ``int` `x: 3; ` `  ``unsigned ``int` `y: 3; ` `  ``int` `z; ` `}; ` ` `  `int` `main() ` `{     ` `   ``union` `test t; ` `   ``t.x = 5; ` `   ``t.y = 4; ` `   ``t.z = 1; ` `   ``printf``(``"t.x = %d, t.y = %d, t.z = %d"``, ` `           ``t.x, t.y, t.z); ` `   ``return` `0; ` `}`

4) Use bit fields in C to figure out a way whether a machine is little endian or big endian.