Characteristics of a Variable
Bit fields are used to consume memory efficiently in such a way that we manage our memory space in a smooth manner.
It can be used in structure and union too.
How To Implement a Bit Field in the C Program
1 2 3 4 5 6 7 8 9 10 11 | struct date { unsigned int d ; unsigned int m ; unsigned int y ; } ; |
Explanation
The variable of type, “date”, takes 12 bytes on a compiler which are 32 bits on a 64-bit compiler, whereas “date” takes 6 bytes on a compiler which are 16 bits.
64 bits
d1 | ||
d | m | y |
22 | 1 | 2016 |
4 bytes | 4 bytes | 4 bytes |
= 12 bytes |
32 bits
d1 | ||
d | m | y |
22 | 1 | 2016 |
2 bytes | 2 bytes | 2 bytes |
= 6 bytes |
How To Reduce the Size of a Variable in a Program
Programming Example 1
In this programming example, we will see what amount of memory is consumed by any type of variable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <stdio.h> struct date // Defining user defined data type. { unsigned int d ; // data member of date data type. unsigned int m ; unsigned in t y ; } ; int main () { struct date d1 = { 22, 1, 2016 } ; // date type variable is declared and initialized. printf ( " Size of d1 is %d ", sizeof ( d1 ) ) ; return 0 ; } |
Output
Explanation
The values of the date and month are fixed: the Date is 31, and the Month is 12.
2 | 31 |
2 | 15-2 |
2 | 7-1 |
2 | 3-1 |
1-1 | |
2 | 12 |
2 | 6-0 |
2 | 3-0 |
1-1 | |
11111 1100 | 1100 |
(5 bits) | (4 bits) |
From the previous calculation of the date, we are trying to say that to represent a maximum day in a month (31), only 5 bits of memory are required out of 4 bytes or 32 bits. It is the same also in the case of counting months. There are 12 months in a year. To represent 12 in the memory, it takes only 4 bits out of 4 bytes or 32 bits. Thus, it is clear from this perception that the rest of the memory is wasted in the case of day and month on a date. In this situation, the bit field helps us to solve the problem.
Programming Example 2
In this programming example, we will use the bit field to consume memory for the variable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #include <stdio.h> struct date // Defining user defined data type. { unsigned int d : 5 ; // data member of date data type. unsigned int m : 4 ; // using bit field as colon : unsigned int y ; } ; int main () { struct date d1 = { 22, 1, 2016 } ; // date type variable is declared and initialized. printf ( " Size of d1 is %d ", sizeof ( d1 ) ) ; return 0 ; } |
Output:
Explanation
We know that the value of d is always from 1 to 31. One year contains 12 months. So, the initialization value of month variable, m, is a maximum of 12. We can handle the extra space with the help of bit fields.
Improved Example
Single memory bytes
[4 bytes] |
Memory block is created multiple of 4 bytes.
The variable d1 of type “date” takes 8 bytes on a compiler, whereas an unsigned integer takes 4 bytes.
Programming Example 3
We will see another example of memory consumption without using a bit field.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #include <stdio.h> struct tm { unsigned int hrs ; unsigned int min ; unsigned int sec ; } ; int main () { struct tm t = {11, 30, 10 } ; // declaration of a variable of user defined type. printf ( " The time is %d : %d : %d\n ", t.hrs, t.min, t.sec ) ; printf ( " The size of clock = %ld bytes.\n ", sizeof ( struct tm ) ) ; return 0 ; } |
Output
Explanation
From the previous calculation of the date, we are trying to say that to represent the maximum seconds in an hour (60), only a 6-bit memory is required out of 4 bytes or 32 bits. It is the same also in the case of counting the minutes. There are 60 minutes in an hour. To represent 60 in the memory, it takes only 5 bits out of 4 bytes or 32 bits. So, it is clear from this perception that the rest of the memory is wasted in the case of day and month on a date. This problem will be solved with the help of the bit field.
Programming Example 4
Here, we can see another application of bit fields.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #include <stdio.h> struct tm { unsigned int hrs : 8 ; unsigned int min : 10 ; unsigned int sec : 10 ; } ; int main() { struct tm t = { 11, 30, 10 } ; // declaration of a variable of user defined type. printf ( " The time is %d : %d : %d\n ", t.hrs, t.min, t.sec ) ; printf ( " The size of clock = %ld bytes.\n ", sizeof ( struct tm ) ) ; return 0 ; } |
Output
Explanation
In this programming example, we use bit field to consume memory. As we see from the example, we will use the bit field (:) after declaring every data member of the time data type, trying to consume bits in a memory location. As a result, we will see from the output memory is consumed.
Conclusion
From the previous declaration, it is evident that we have to use the bit field to manage space complexity in the C language. Bit field helps us to remove extra wasted memory allocation from the memory to manage space complexity. So, we must use the bit field in a very conscious manner where it is required. Otherwise, data may be wasted.