Jan 9, 2016

C Programming #58: Structure - bit-fields

Among all the built in type in C Programming language char, int, long, float, double; char is smallest in size. It is always 8 bits regardless of whichever architecture (32bit, 64bit) code is completed to. Say if you want to store something which is smaller than char ? (Bit-fields can be used, that's why this question in this article). This article covers the topic of bit-fields in detail.


Lets take following structure_t as example-

typedef struct {
   char name[20];
   int class;
   int age;
}student_t;

Typical value of class can be anything between 1 to 12, age can be typically between 1 to 100. Hence to store maximum value of class we need 4 bits. Maximum value of age can be stored in 7 bits.

Using bit-fields, new structure would look like. Note the syntax which is used to mention number of bits required.

typedef struct {
   char name[20];
   int class:4;
   int age:7;
}student_new_t;

Following program gives example of use of bit-fields-

#include <stdio.h>

typedef struct {
  char name[20];
  int class;
  int age;
}student_t;

typedef struct {
  char name[20];
  int class:4;
  int age:7;
}student_new_t;

int main(void)
{
  student_t a = {"Ram", 7, 2};
  student_new_t b = {"Mason", 9, 4};

  printf("Student %s age is %d and studies in %d\n",
         a.name, a.age, a.class);
  printf("Student %s age is %d and studies in %d\n",
         b.name, b.age, b.class);

  printf("sizeof student_t is %d\n", sizeof(student_t));
  printf("sizeof student_new_t is %d\n", sizeof(student_new_t));

  return 0;
}

Output of above program is

Student Ram age is 2 and studies in 7
Student Mason age is 4 and studies in -7
sizeof student_t is 28
sizeof student_new_t is 24

Size calculation for student_t

  • name is 20 bytes
  • class is 4 bytes
  • age is 4 bytes
  • Hence totally structure is 28
Size calculation for student_new_t

  • name is still 20 bytes
  • class and age are bit-fields inside a integer hence 4 bytes.
  • Hence total structure is 24


In this particular case bit-field int (32 bit) would contain class (4 bit) and age (7 bit). Other 21 bits are waste here. Note that bit-fields are not addressable. &b.class or &b.age would result in error, Following program gives that an example.

#include <stdio.h>

typedef struct {
  char name[20];
  int class:4;
  int age:7;
}student_new_t;

int main(void)
{
  student_new_t b = {"Mason", 9, 4};

  printf("Student %s age is %d and studies in %d\n",
         b.name, b.age, b.class);
  printf("Address of name is %p, address of class is %p,"
          "address of age is %p\n",
         &b.name, &b.class, &b.age);
  return 0;
}
Compilation error of above program is

pi@raspberrypi:~/ws/cprog $ gcc 58-structure_bitfields_error.c
58-structure_bitfields_error.c: In function "main":
58-structure_bitfields_error.c:17:3: error: cannot take address of bit-field "class"
   &b.name, &b.class, &b.age);
   ^
58-structure_bitfields_error.c:17:3: error: cannot take address of bit-field "age"

Now lets take one more variation.

typedef struct {
   char name[20];
   char class:4;
   char age:7;
}student_newx_t;

Here both class (4 bits) and age (7 bits) cannot be accommodated in same char, hence in this case two chars would be allocated.

#include <stdio.h>

typedef struct {
  char name[20];
  char class:4;
  char age:7;
}student_new_t;

int main(void)
{
  student_new_t b = {"Mason", 9, 4};

  printf("Student %s age is %d and studies in %d\n",
         b.name, b.age, b.class);
  printf("Size of student_new_t is %d\n", sizeof(student_new_t));

  return 0;
}

Output of the above program is


Student Mason age is 4 and studies in 9
Size of student_new_t is 22

Calculation of sizeof(student_new_t in above program).
  • name is still 20 bytes
  • class will fit in char bit-field which is 1 byte.
  • age will fit in char bit-field which is 1 bytes.
  • Hence total structure is 22

Now say i add one more member variable called sex which is 2 bits
typedef struct {
   char name[20];
   char class:4;
   char age:7;
   char sex:2;
}student_newx_t;

Program

#include <stdio.h>

#define MALE 1
#define FEMALE 2

typedef struct {
  char name[20];
  char class:4;
  char age:7;
  char sex:2;
}student_new_t;

int main(void)
{
  student_new_t b = {"Mason", 9, 4, MALE};

  printf("Student %s age is %d sex is %d and studies in %d\n",
         b.name, b.age, b.sex, b.class);
  printf("Size of student_new_t is %d\n", sizeof(student_new_t));

  return 0;
}

Output of the above program is

Student Mason age is 4 sex is 1 and studies in 9
Size of student_new_t is 23

Calculation of sizeof(student_new_t)

  • name is still 20 bytes
  • class (4 bits) will fit in char bitfield which is 1 byte.
  • age (7 bits) will fit in char bitfield which is 1 byte.
  • sex (2 bits) which cannot fit in above above char hence will take new char which is 1 bytes
  • Hence total structure is 23 bytes.

If you look closely it can be compacted further as
typedef struct {
  char name[20];
  char class:4;
  char sex:2;
  char age:7;
}student_new_t;

Calculation of sizeof(student_new_t)

  • name is still 20 bytes
  • class (4 bits) and sex (2 bit) will fit in char bit-field which is 1 byte.
  • age (7 bits) will fit in char bit-field which is 1 byte.
  • Hence total structure is 22 bytes.

Typical examples of this kind of data structure is

  1. Optimizing the structure for compacting size.
  2. For representing several flags.
  3. To represent Register fields in embedded programming.

Links

All Article - C Programming

No comments :

Post a Comment