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.
Output:
Output:
1) A special unnamed bit field of size 0 is used to force alignment on next boundary. For example consider the following program.
Output:
2) We cannot have pointers to bit field members as they may not start at a byte boundary.
Output:
3) It is implementation defined to assign an out-of-range value to a bit field member.
Output:
4) In C++, we can have static members in a structure/class, but bit fields cannot be static.
5) Array of bit fields is not allowed. For example, the below program fails in compilation.
Output:
For example, consider the following declaration of date without use of bit fields.
#include <stdio.h> // 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\n" , sizeof ( struct date)); struct date dt = {31, 12, 2014}; printf ( "Date is %d/%d/%d" , dt.d, dt.m, dt.y); } |
Size of date is 12 bytes Date is 31/12/2014The 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 <stdio.h> // 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 12 bits // are sufficient unsigned int m: 4; unsigned int y; }; int main() { printf ( "Size of date is %d bytes\n" , sizeof ( struct date)); struct date dt = {31, 12, 2014}; printf ( "Date is %d/%d/%d" , dt.d, dt.m, dt.y); return 0; } |
Size of date is 8 bytes Date is 31/12/2014Following 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 <stdio.h> // 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\n" , sizeof ( struct test1)); printf ( "Size of test2 is %d bytes\n" , sizeof ( struct test2)); return 0; } |
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 <stdio.h> struct test { unsigned int x: 5; unsigned int y: 5; unsigned int z; }; int main() { 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; } |
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 <stdio.h> struct test { unsigned int x: 2; unsigned int y: 2; unsigned int z: 2; }; int main() { test t; t.x = 5; printf ( "%d" , t.x); return 0; } |
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[10]: 5; }; int main() { } |
error: bit-field 'x' has invalid type
No comments:
Post a Comment