Open In App

C++ Bit Fields

Last Updated : 06 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

When we declare the members in a struct and classes, a pre-determined size is allocated for the member variables. In C++, we can compress that allocated size using bit fields.

Bit Field is a feature in C++ for specifying the size of struct and class members so that they occupy a specific number of bits, not the default memory size.

For example, an integer takes 4 bytes of size but this size is large according to our requirements so we can change it to 2 bytes using bit fields.

Syntax of Bit Field in C++

In C++, we can define a bit field by specifying the data type and then the field name with the desired width in bits.

Bit-Field Syntax in Struct

struct StructName {
    dataType fieldName : width;
    // more bit-field members...
};

Bit-Field Syntax in Classes

class ClassName {
public:
    dataType fieldName : width;
    // more bit-field members...
};

where width is the number of bits.

Note: It is to be noted that bit fields are only acceptable for integral data types.

Example of C++ Bit Fields

The following examples demonstrate the use of bit fields in both structures and classes.

Example 1: Bit Fields in Structures

In the below example,  we will compare the size difference between the structure that does not specify bit fields and the structure that has specified bit fields.

C++




// C++ program to demonstrate the size occupied by a struct
// with and without bitfields
#include <iostream>
using namespace std;
 
// Define a struct without bit fields
struct Loan1 {
    unsigned int principal;
    unsigned int interestRate;
    unsigned int period;
};
 
// Define a struct with bit-fields
struct Loan2 {
    // principal variable can store maximum value of
    // 1,048,575
    unsigned int principal : 20;
    // Maximum interest rate of 63
    unsigned int interestRate : 6;
    // Maximum period of 63 months
    unsigned int period : 6;
};
 
int main()
{
    // printing the size of both structures
    cout << "Size of Structure without Bit Fields: ";
    cout << sizeof(Loan1) << " Bytes" << endl;
    cout << "Size of Structure with Bit Fields: ";
    cout << sizeof(Loan2) << " Bytes" << endl;
    return 0;
}


Output

Size of Structure without Bit Fields: 12 Bytes
Size of Structure with Bit Fields: 4 Bytes

Explanation

  • For the structure ‘Loan’, the size is 12 bytes which accounts for 4 bytes for each of the three integer members.
  • In structure ‘Loan2″, we have used bit fields to specify the memory allocated to the member variables of a struct in bits.
  • We have specified 20 bits for ‘principal’, 6 bits for ‘interest rate’, and 6 bits for ‘period’.
  • They all contributed to 32 bits which is equal to 4 Bytes which is why the size of ‘Loan2″ is 4 bytes.

Example 2: Class with Bit Fields in C++

In the below example, we have used bit fields with classes instead of struct.

C++




// C++ program to demonstrate the size occupied by a class
// by specifying the bits to member variables of the class
// using bit fields
#include <iostream>
using namespace std;
 
// Define a class with bit-fields for loan information
class Loan {
public:
    // Maximum principal of 1,048,575
    unsigned int principal : 20;
    // Maximum interest rate of 63
    unsigned int interestRate : 6;
    // Maximum period of 63 months
    unsigned int period : 6;
};
 
int main()
{
    Loan loan1;
    loan1.principal = 500000;
    loan1.interestRate = 15;
    loan1.period = 36;
 
    // Print the size of loan1
    // (20+6+6)/8 = 4 Bytes
    // 1 Byte = 8 Bits
    cout << sizeof(Loan) << " Bytes" << endl;
 
    return 0;
}


Output

4 Bytes

Explanation

In the above example, we have used bit fields to specify the memory allocated to the member variables of a class in bits. We have specified 20 bits for ‘principal’, 6 bits for ‘interest rate’, and 6 bits for ‘period’. They all contributed to 32 bits which is equal to 4 Bytes.

Some Interesting Facts about Bit Fields

1. The number of bits assigned to a member variable can be greater than the default size of the data type of variable.

C++




// C++ program to demonstrate that the number of bits
// assigned to a member variablecan be greater than the
// default size of the data type of variable.
#include <bits/stdc++.h>
using namespace std;
 
// Define a structure with bit fields
struct values {
    int num : 520;
};
 
int main()
{
    values val1;
    // Assigning value to num variable
    val1.num = 1;
    // Print the size of struct
    cout << sizeof(val1) << " Bytes" << endl;
 
    return 0;
}


Output

80 Bytes

Explanation

The num variable is assigned 520 bits, which (assuming a 32-bit or 4-byte int) would require 16.25 ints or 65 bytes to represent. Rounding up it to the upper limit of 17, 17*32 bits=544 bits would have been enough to store the requested value, but compiler padding and alignment issues push the allotment to 80 bytes i.e. 640 bits or 20 ints.

2. We can not create pointers that point to bit fields because they might not start at a byte boundary.

C++




// C++ program to demonstrate that we can not create
// pointers that points to bit fields
#include <iostream>
using namespace std;
 
struct BitField {
    unsigned int num : 1;
};
 
int main()
{
    BitField var;
    var.num = 1;
 
    // Error: Cannot take the address of a bit field
    // unsigned
    unsigned int* ptr = &var.num;
 
    // Error: Cannot create a reference to a bit field
    int& ref = var.num;
 
    cout << var.num << endl;
 
    return 0;
}


Output

./Solution.cpp: In function 'int main()':
./Solution.cpp:15:30: error: attempt to take address of bit-field structure member 'BitField::num'
     unsigned int* ptr = &var.num;
                              ^
./Solution.cpp:18:20: error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
     int& ref = var.num;
                    ^

Applications of Bit Fields in C++

  1. It is majorly used for memory optimization as it allows us to use only the necessary number of bits to represent a member variable which reduces memory overhead.
  2. It can be used to compress the data so that it can take less time to transfer data from one point to another over the network.  
  3. It can be used to design hardware registers that have specific bit structures.
  4. In graphics applications, color components, pixel formats, and image data often have specific bit requirements which can be customized using bit fields.


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads