The following two examples demonstrate the use of bit fields to reduce memory consumption of certain applications.
In the first example we create a compressed ‘bit’ struct and on the second we create a weird struct representation for bytes to show that the size of that struct is significantly less that the original one.
First example: Using bit fields to create a ‘bit’ structure
[download id=”2693″]
#include <stdio.h>
// Weird structure to represent a 'bit'
typedef struct {
unsigned char value;
} bit;
// 'bit' structure using bit fields
typedef struct {
unsigned char value : 1;
} bit_bit_field;
int main( ) {
printf( "Memory size occupied by 'bit' struct : %zu bytes\n", sizeof(bit));
printf( "Memory size occupied by 'bit_bit_field' struct : %zu bytes\n", sizeof(bit_bit_field));
bit bits[8];
bit_bit_field bits_bit_field[8];
printf( "Memory size occupied by 'bits' array : %zu bytes\n", sizeof(bits));
printf( "Memory size occupied by 'bits_bit_field' array : %zu bytes\n", sizeof(bits_bit_field));
// Setting the value of the first 'bit' and then printing it.
// We will use various values for this test to show that when you set a value to a bit field
// that is greater that the allowed size it will fill it using the last bits only.
// It will not spill data though to neighbouring 'bits'.
unsigned char value;
for (value = 0; value < 4; value++)
{
printf("Input Value: %d\n", value);
int bits_i;
const int bits_length = (sizeof(bits) / sizeof(bit));
for (bits_i = 0; bits_i < bits_length; bits_i++)
{
if (bits_i % 2)
{
bits[bits_i].value = 0;
}
else
{
bits[bits_i].value = value;
}
printf("%d", bits[bits_i].value);
}
printf("\n");
int bits_bit_field_i;
const int bits_bit_field_length = (sizeof(bits_bit_field) / sizeof(bit_bit_field));
for (bits_bit_field_i = 0; bits_bit_field_i < bits_bit_field_length; bits_bit_field_i++)
{
if (bits_bit_field_i % 2)
{
bits_bit_field[bits_bit_field_i].value = 0;
}
else
{
bits_bit_field[bits_bit_field_i].value = value;
}
printf("%d", bits_bit_field[bits_bit_field_i].value);
}
printf("\n");
}
return 0;
}
[download id=”2693″]
Execution output
Memory size occupied by 'bit' struct : 1 bytes Memory size occupied by 'bit_bit_field' struct : 1 bytes Memory size occupied by 'bits' array : 8 bytes Memory size occupied by 'bits_bit_field' array : 8 bytes Input Value: 0 00000000 00000000 Input Value: 1 10101010 10101010 Input Value: 2 20202020 00000000 Input Value: 3 30303030 10101010
Second example: Using bit fields to create a ‘byte’ structure where each ‘bit’ is another named member
[download id=”2692″]
#include <stdio.h>
// Weird structure to represent a 'byte'
typedef struct {
unsigned char bit_0;
unsigned char bit_1;
unsigned char bit_2;
unsigned char bit_3;
unsigned char bit_4;
unsigned char bit_5;
unsigned char bit_6;
unsigned char bit_7;
} byte;
// 'byte' structure using bit fields
// Unfortunately we cannot declare an array where the values are bit fields,
// so we have to declare each member separately.
// We instruct the compiler to use only one bit per element.
typedef struct {
unsigned char bit_0 : 1;
unsigned char bit_1 : 1;
unsigned char bit_2 : 1;
unsigned char bit_3 : 1;
unsigned char bit_4 : 1;
unsigned char bit_5 : 1;
unsigned char bit_6 : 1;
unsigned char bit_7 : 1;
} byte_bit_field;
int main( ) {
printf( "Memory size occupied by 'byte' struct : %zu bytes\n", sizeof(byte));
printf( "Memory size occupied by 'byte_bit_field' struct : %zu bytes\n", sizeof(byte_bit_field));
byte bytes[8];
byte_bit_field bytes_bit_field[8];
printf( "Memory size occupied by 'bytes' array : %zu bytes\n", sizeof(bytes));
printf( "Memory size occupied by 'bytes_bit_field' array : %zu bytes\n", sizeof(bytes_bit_field));
// Setting the value of the first 'bit' and then printing it.
// We will use various values for this test to show that when you set a value to a bit field
// that is greater that the allowed size it will fill it using the last bits only.
// It will not spill data though to neighbouring 'bits'.
unsigned char value;
for (value = 0; value < 4; value++)
{
printf("Input Value: %d\n", value);
int bytes_i;
const int bytes_length = (sizeof(bytes) / sizeof(byte));
for (bytes_i = 0; bytes_i < bytes_length; bytes_i++)
{
if (bytes_i % 2)
{
bytes[bytes_i].bit_3 = 0;
}
else
{
bytes[bytes_i].bit_3 = value;
}
printf(" %d ", bytes[bytes_i].bit_3);
}
printf("\n");
int bytes_bit_field_i;
const int bytes_bit_field_length = (sizeof(bytes_bit_field) / sizeof(byte_bit_field));
for (bytes_bit_field_i = 0; bytes_bit_field_i < bytes_bit_field_length; bytes_bit_field_i++)
{
if (bytes_bit_field_i % 2)
{
bytes_bit_field[bytes_bit_field_i].bit_3 = 0;
}
else
{
bytes_bit_field[bytes_bit_field_i].bit_3 = value;
}
printf("%d%d%d ",
bytes_bit_field[bytes_bit_field_i].bit_2,
bytes_bit_field[bytes_bit_field_i].bit_3,
bytes_bit_field[bytes_bit_field_i].bit_4);
}
printf("\n");
}
return 0;
}
[download id=”2692″]
Execution output
Memory size occupied by 'byte' struct : 8 bytes Memory size occupied by 'byte_bit_field' struct : 1 bytes Memory size occupied by 'bytes' array : 64 bytes Memory size occupied by 'bytes_bit_field' array : 8 bytes Input Value: 0 0 0 0 0 0 0 0 0 000 000 000 000 000 000 000 000 Input Value: 1 1 0 1 0 1 0 1 0 010 000 010 000 010 000 010 000 Input Value: 2 2 0 2 0 2 0 2 0 000 000 000 000 000 000 000 000 Input Value: 3 3 0 3 0 3 0 3 0 010 000 010 000 010 000 010 000
This post is also available in: Greek


