≡ Menu

How to Use C Structures, Unions and Bit Fields with Examples

Structures, Unions and Bit fields are some of the important aspects of C programming language.

While structures are widely used, unions and bit fields are comparatively less used but that does not undermine their importance.

In this tutorial we will explain the concept of Structures, Unions and Bit fields in C language using examples.

1. Structures in C

Structure provides a way to store multiple variables of similar or different types under one umbrella. This makes information more packaged and program more modular as different variables referring to different values can be accessed through a single structure object.

An example of a C structure can be :

struct <Name or Tag>
     {
         <member-1>;
         <member-2>;
         <member-3>;
         ...
         ...
         ...
     };

So we see that a structure can be defined through a keyword ‘struct’ followed by structure name. The body of structure consists of different semicolon terminated variable definitions within curly braces.

Going back to what structure really is, A structure usually does not package unrelated variables. All the variables are usually part of some broader level information that structure intends to hold.

For example, a structure can hold all the information related to an employee in an organization:

struct employee
     {
        char *name;
        int age;
        char *department;
        int salary;
        char *job_title;
     };

Now, to access a structure variables, you need to define an object for that structure. For example, here is how you can define an object for the ’employee’ structure :

struct employee emp_obj;

NOTE: The keyword ‘struct’ is mandatory while defining structure objects in C

The variable ’emp_obj’ now becomes object of ’employee’ structure. Individual structure members can be accessed in the following way :

     emp_obj.name
     emp_obj.age
     ...
     ...
     ...

So we see that ‘.’ is used to access individual variables

Unlike the one above, a structure object can also be of a pointer type. For example :

struct employee *emp_obj;

In this case, individual structure members can be accessed in the following way :

     emp_obj->name
     emp_obj->age
     ...
     ...
     ...

So we see that ‘->’ is used to access individual variables.

Here is a working example of C structure :

#include <stdio.h> 

struct employee
{
   char *name;
   int age;
   char *department;
   int salary;
   char *job_title;
};

int main(void)
{
   struct employee emp_obj;
   struct employee *emp_ptr_obj;

   emp_obj.name = "theGeekStuff";
   /* Similarly Initialize other
    * variables of employee
    * structure here */

   emp_ptr_obj = &emp_obj;

   printf("\n Employee name is [%s]\n", emp_ptr_obj->name);

   return 0;
}

Here is the output :

Employee name is [theGeekStuff]

2. Unions in C

Unions are almost like structures in C (just explained above) but with a twist. The twist is that the memory for a union is equal to the size of it’s largest member. Confused? No worries, lets understand it in more detail.

Here is how Unions are defined :

union char_and_ascii
{
   char ch;
   unsigned int ascii_val;
};

As you can see that it’s more or less like how we declare structures in C. Just that the keyword ‘union’ is used instead of ‘struct’.

So, what is the difference between a structure and a union? Well, the difference lies in the size. If the above example would have been a structure, the size of structure would have been :

sizeof(char) + sizeof(unsigned int)

ie 1 + 4 = 5 bytes.

But, in case of a union, the size is equivalent to that of the largest member type in union. So, in this case, the largest type is ‘unsigned int’ and hence the size of union becomes ‘4’.

Now, having understood that, one might ask, in which scenarios union can be used? Well, there are certain scenarios where you want to use only one of the members at a time. So in that case, using a union is a wise option rather than using a structure. This will save you memory.

Here is a working example of a Union in C :

#include <stdio.h>

union char_and_ascii
{
    char ch;
    unsigned short ascii_val;
};

int main (void)
{
    union char_and_ascii obj;
    obj.ascii_val = 0;

    obj.ch = 'A';

    printf("\n character = [%c], ascii_value = [%u]\n", obj.ch, obj.ascii_val);

    return 0;
}

Here is the output :

character = [A], ascii_value = [65]

On a different note, to get more deeper understanding of C language, you should also know how C Macros / Inline Functions and C Binary Tree works.

3. Bit fields in C

There are times when the member variables of a structure represent some flags that store either 0 or 1. Here is an example :

struct info
{
    int isMemoryFreed;
    int isObjectAllocated;
}

If you observe, though a value of 0 or 1 would be stored in these variables but the memory used would be complete 8 bytes.

To reduce memory consumption when it is known that only some bits would be used for a variable, the concept of bit fields can be used.

Bit fields allow efficient packaging of data in the memory. Here is how bit fields are defined :

struct info
{
    int isMemoryFreed : 1;
    int isObjectAllocated : 1;
}

The above declaration tells the compiler that only 1 bit each from the two variables would be used. After seeing this, the compiler reduces the memory size of the structure.

Here is an example that illustrates this :

#include <stdio.h>

struct example1
{
    int isMemoryAllocated;
    int isObjectAllocated;
};

struct example2
{
    int isMemoryAllocated : 1;
    int isObjectAllocated : 1;
};

int main(void)
{
    printf("\n sizeof example1 is [%u], sizeof example2 is [%u]\n", sizeof(struct example1), sizeof(struct example2));

    return 0;
}

Here is the output :

sizeof example1 is [8], sizeof example2 is [4]

Also, if after declaring the bit field width (1 in case of above example), if you try to access other bits then compiler would not allow you to do the same.

Here is an example :

#include <stdio.h>

struct example2
{
    int isMemoryAllocated : 1;
    int isObjectAllocated : 1;
};

int main(void)
{
    struct example2 obj;

    obj.isMemoryAllocated = 2;

   return 0;
}

So, by setting the value to ‘2’, we try to access more than 1 bits. Here is what compiler complains :

$ gcc -Wall bitf.c -o bitf
bitf.c: In function ‘main’:
bitf.c:14:5: warning: overflow in implicit constant conversion [-Woverflow]

So we see that compiler effectively treats the variables size as 1 bit only.

Add your comment

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

Comments on this entry are closed.

  • Jalal Hajigholamali August 8, 2013, 8:32 am

    Hi,

    Thanks a lot,

    Very useful article..

  • Arlen August 8, 2013, 9:13 am

    A useful use of unions is to provide a mechanism to interact with embedded electronics devices which have registers which are controlled by bits in registers, in groups of one or more contiguous bits. I.E. single bit flags to indicate interrupt status, the receipt of a character in a UART, etc, or three or more bits in a contiguous block which may indicate the number of bytes available in a UART receive buffer for example.

    In this use case, proper use of unions can make the code easier to understand by code maintainers.

    Update: Sorry, I meant bitfields.

  • Filipe Gonçalves August 8, 2013, 9:14 am

    You have an error in your article. When you talk about unions vs. structures, you say that an equivalent structure would have the size of sizeof(char)+sizeof(int). This is not true. The size of a structure is not the sum of its elements because of alignment issues. A structure with an unsigned int and a char may have sizeof = 8.

    Output to the following code is: 8

    #include 
     
    struct test {
        char a;
        unsigned int b;
    };
     
    int main() {
        printf("%zu\n", sizeof(struct test));
        return 0;
    }
    
  • Bob August 8, 2013, 9:25 am

    thanks. useful refresher…

  • Claudio August 8, 2013, 10:18 am

    It would also be good to mention memory consumption of structs.
    For example:
    struct char_and_ascii
    {
    char ch;
    unsigned int ascii_val;
    };

    Someone would expect that sizeof( char_and_ascii ) = 5, but most of the time, it will be bigger, because of the padding that is added.

    So if you allocate memory for a struct and you write to it, it could be possible that you are already out of bounds, but because of the extra memory allocated for the padding you won’t get a segmentation fault.

  • Rajesh August 8, 2013, 11:16 pm

    Hi,

    Very nice article.

    Keep it Up.

  • PSDK August 10, 2013, 1:26 am

    Hi,
    Thanks a lot for this nice article.

  • karthik August 11, 2013, 1:30 am

    how, sizeof(example2) is 4 in the concept of BIT FIELDS IN C ? I didn’t get it.

  • TurboPT September 15, 2013, 8:48 pm

    @karthik:
    As there are 32 bits in 4 bytes, and only 2 bits of these are used [leaving 30 other bits NOT used], the example2 structure only needs ONE int to handle 32 bits.

  • Michal October 9, 2013, 2:43 am

    The example of using a union is non-standard (although it is a commonly used trick). The standard, however, allows only reading the union through that member which was last assigned. Thus, using obj.ascii_val in printf is forbidden by standard.
    Also, the code sample would give “[65]” as the obj.ascii_val value ONLY in little-endian architecture. On a Sparc machine, or any other big-endian computer, it would be “[16640]” (decimal equivalent of hex 0x4100). This is one of the reasons why the standard forbids such a use.
    Needless to say, be it legal or not, such a construct can be a very easy way to detect the endianess programatically.

  • Anonymous January 15, 2014, 2:09 am

    Nice one, thank you!

  • Mazhar Abbas January 4, 2016, 1:20 pm

    Very helpful. Thanks

  • majid March 4, 2016, 5:57 am

    This articles are really Amazing, they help me to understand everything in a simple way.