Bit Fields in C Programming with Examples

This C Tutorial explains Bit Fields in C Language with examples.

Bit fields in C are a type of data structure used to store data in a series of bits. Structures in C are capable of implementing bit fields. Bit fields are declared as other structure declarations with difference that member’s are fields of one or more bits. These variable length fields are stored together in one or more integers. This means that bit fields allow us to access particular fields stored in an integer.

Let’s see how can we declare a structure with bit fields:

struct CHAR {
             unsigned ch    : 7;
             unsigned font  : 6;
             unsigned size  : 19;
        };

Notice that bit fields are declared as normal structure declaration but with two limitations, first, all member’s (bit fields) are declared to be unsigned and second each member is followed by colon and an integer. Integer specifies no. of bits in a particular field.

Above declaration is from a text formatting program, which uses concept of bit fields to implement several different characteristics of a character viz. no. of characters, different fonts, and font sizes etc.. Member ‘ch’ takes 7 bits to represent all possible 128 different characters, ‘font’ takes 6 bits to handle all 64 different possibilities and ‘size’ takes 19 bits to suffice for 2 raised to power 19 possibilities. All three bit fields are stored in one integer on machine with word size 32-bits. Let’s create a variable of CHAR structure,

    struct CHAR ch1;

On machines with word size of 16-bits, compiler will flag the above declaration as illegal. While on machines with word size of 32 bits, compiler packs them in one integer but in which order i.e. either from left to right or from right to left.

advertisement
advertisement

Bit Fields Limitations:
Because of several implementation dependencies, bit fields work differently on different systems. Programs intended to be portable should avoid bit fields. Let’s, first, see these limitations,

1. Since bit fields are type ‘int’. And an ‘int’ can be interpreted as signed or unsigned on particular machine. It’s a better idea to explicitly declare bit fields as unsigned.

2. Order of bit fields in an integer, is either from left to right or from right to left.

Sanfoundry Certification Contest of the Month is Live. 100+ Subjects. Participate Now!

3. A bit field declaration on machine with word size of 32-bits may not work on machine with word size of 16-bits.

4. If a declaration specifies two bit fields, and second is too large to fit in the bits left over from the first, compiler can either store the second in next word in memory or immediately after the first with overlapping boundary between memory locations.

Thus far, we have seen how bit fields reduced the memory wastage by packing variable length fields into one or more integers. This savings becomes important when hundreds of such structures are created.

Let’s understand bit fields implementation through a practical example, that might be found in some operating system. The code to operate the floppy disk must communicate with the controller for the disk. Often these device controllers contain several registers, each of which contains many different values all packed together into one integer. A bit field is a convenient way to access the individual values. Let’s have the declaration for one such register, on a machine which allocated bit fields
from right to left, the following declaration would allow easy access to various fields in the register,

advertisement
struct DISK_REGISTER_FORMAT {
    unsigned    command            : 5;
    unsigned    sector             : 5;
    unsigned    track              : 9;
    unsigned    error_code         : 8;
    unsigned    head_loaded        : 1;
    unsigned    write_protect      : 1;
    unsigned    disk_spinning      : 1;
    unsigned    error_occurred     : 1;
    unsigned    ready              : 1;
};

If this disk register is accessed at the memory address Oxabcfff12, we can define a pointer constant as,

    #define DISK_REGISTER ((struct DISK_REGISTER_FORMAT *)Oxabcfff12)

With this preparation, the code needed to actually access the disk register is simple, consider for example,

advertisement
/*
 * tell the controller which sector and track to access and perform read
 * operation
 */
 
    DISK_REGISTER->sector = new_sector;
    DISK_REGISTER->track  = new_track;
    DISK_REGISTER->command= READ;
 
    /* wait until READ operation done indicated by 'ready' becoming true */
 
    while (!DISK_REGISTER->ready)
        ;
 
    /* Now, check for any errors if occurred */
 
    if (DISK_REGISTER->error_occurred)
        switch (DISK_REGISTER->error_code) {
 
                /* various cases */
        }

So, how beautiful was it that we accessed individual fields in an integer using bit fields concept!

Sanfoundry Global Education & Learning Series – 1000 C Tutorials.

If you wish to look at all C Tutorials, go to C Tutorials.

advertisement
advertisement
Subscribe to our Newsletters (Subject-wise). Participate in the Sanfoundry Certification contest to get free Certificate of Merit. Join our social networks below and stay updated with latest contests, videos, internships and jobs!

Youtube | Telegram | LinkedIn | Instagram | Facebook | Twitter | Pinterest
Manish Bhojasia - Founder & CTO at Sanfoundry
Manish Bhojasia, a technology veteran with 20+ years @ Cisco & Wipro, is Founder and CTO at Sanfoundry. He lives in Bangalore, and focuses on development of Linux Kernel, SAN Technologies, Advanced C, Data Structures & Alogrithms. Stay connected with him at LinkedIn.

Subscribe to his free Masterclasses at Youtube & discussions at Telegram SanfoundryClasses.