This article is the continuation of the Series on the C programming tutorial and carries the discussion on C language programming and its implementation. It aims to provide easy and practical examples for understanding the C program. In our last article, we have seen the Strings in C programming. In this article, we will see structures in C programming.
There are many built-in data types are available in the C programming language. User also can create their own data types using Structures, Unions, Bit-Fields, typedef, and enum. In this article, we will see the Structure, Structure Pointers, Structure padding, and Bit fields in C Programming.
Structures, Structure Pointers, Structure padding, Bit fields in C Programming
Structures in C Programming
What is a structure in C?
A structure is a collection of one or more variables (possibly of different types) grouped together under a single name for easy to handling. In other words, structures in C programming are the collection of dissimilar data types. We can group the related parameters or variables to the unit. So, the Structures in C help to organize complicated data, particularly in large programs.
An example of a structure is the employee record: an employee is described by a set of attributes such as name, designation, salary, ID, address, sex, etc.
struct employee { char Name[50]; char designation[50]; char address[100]; int Id; float Salary; } info;
The keyword struct
introduces a structure declaration. An optional name called a structure tag may follow the word struct
(as with employee here). The variables named inside a structure are called members.
How do we access the structure’s members?
We can access the members of the structure in two ways.
- . (dot operator)
- -> (structure pointer operator)
If we want to assign the values to the members, we assign them as below.
info.Id = 12; info.Salary = 30000;
What is a structure pointer in C programming?
As you know pointer is the variable that points to the address of another variable, structure pointer is the variable that stores the address of the structure variable.
The structure pointer can be defined as below.
struct emp *ptr;
Initialization
struct emp *ptr = &structure_variable;
Example
#include <stdio.h> struct Subject { char sub_Name[30]; int sub_Marks; }; int main() { struct Subject sub; // declare the Subject variable struct Subject *ptr; // create a pointer variable (*ptr) ptr = ⊂ // ptr variable pointing to the address of the structure variable sub strcpy (sub.sub_Name, "C Programming EmbeTronicX"); sub.sub_Marks = 350; //out of 500 // print the details of the Subject (Structure pointer) printf (" Subject Name: %s\n ", ptr->sub_Name); printf (" Subject Marks: %d\n\n ", ptr->sub_Marks); // print the details of the Subject (Structure) printf (" Subject Name: %s\n ", sub.sub_Name); printf (" Subject Marks: %d\n ", sub.sub_Marks); return 0; }
Output
Subject Name: C Programming EmbeTronicX Subject Marks: 350 Subject Name: C Programming EmbeTronicX Subject Marks: 350
An array of structures in C programming
Arrays and structures are two fundamental concepts in C programming. An array is a collection of similar data types and structures are a collection of dissimilar data types. Can we merge this two? Yes, we can. We can create an array of structures. Combining these two allows you to create an array of structures, where each element of the array is a structure. This can be useful when you need to store and manipulate multiple related pieces of data.
An array of structures in C can be defined as the collection of multiple structures variables where each variable contains information about different entities. The array of structures in C is used to store information about multiple entities of different data types. The array of structures is also known as the collection of structures.
Example
The below example will help you to understand an array of structures.
#include<stdio.h> #include <string.h> struct student { int rollno; char name[10]; }; int main() { int i; struct student st[3]; printf("Enter Records of 3 students\n"); for(i=0;i<3;i++) { printf("Enter Rollno: "); scanf("%d",&st[i].rollno); printf("\nEnter Name: "); scanf("%s",&st[i].name); } printf("\n\nStudent Information List:\n"); for(i=0;i<3;i++) { printf("Rollno:%d, Name:%s\n",st[i].rollno,st[i].name); } return 0; }
Output
Enter Records of 3 students Enter Rollno: 10 Enter Name: Arun Enter Rollno: 11 Enter Name: John Enter Rollno: 12 Enter Name: Raj Student Information List: Rollno:10, Name:Arun Rollno:11, Name:John Rollno:12, Name:Raj
Using an array of structures can be helpful when you want to work with multiple related data entities simultaneously. You can easily iterate over the array, perform operations on the individual elements, or search for specific data based on certain conditions.
Remember to allocate enough memory for your array based on the number of elements you intend to store, and be careful to avoid accessing elements outside the valid range of the array.
This is a basic overview of using an array of structures in C programming. It’s a powerful technique that can simplify handling multiple pieces of related data.
Structure padding in C programming
Till now we have seen some basics of the structures in C programming. Now we will go a little bit deeper into the structure.
Assume we are using the typical 32-bit machine, where char is 1byte, short int is 2 bytes, int is 4 bytes, and double is 8 bytes.
Now tell me, what is the size of the below structure?
typedef struct { int a; // 4 Bytes int b; // 4 Bytes } temp;
Yes, totally 8 bytes.
What about the below structures temp1
and temp2
?
typedef struct { char a; // 1 byte int b; // 4 bytes } temp1; typedef struct { char a; // 1 byte int b; // 4 bytes char c; // 1 byte } temp2;
The size of the temp1
is 5 bytes and the size of the temp2
is 6 bytes, right? But sadly no. The original answer is 8 bytes and 12 bytes respectively. These extra 3 bytes and 6 bytes are called structure padding.
How come? Okay, we will see the concept. First, you need to know about memory alignment and memory access.
Memory Alignment
Computers commonly address their memory in word-sized chunks. A word is a computer’s natural unit for data. Its size is defined by the computer’s architecture. On a 32-bit machine, the word size will be 4 bytes. So, the processor does not read 1 byte at a time. It reads 1 word (4 bytes) at a time.
If an integer of 4 bytes is allocated on the address that is a multiple of 4 (eg. 0, 4, 8, 12, 16, 20,…. etc), the processor needs only one memory cycle to read the entire integer. Whereas, if the integer is allocated at an address other than a multiple of 4 (eg.1, 5, 7, 10, … etc), it requires two memory read cycles to fetch the data. Confused? Okay, we will explain it in a different way.
The three word-sized memory cells in a 32-bit machine are given below.
0x00000000 | 0x00000004 | 0x00000008 | |||||||||
If you are adding a 4-byte integer X
to the memory with proper alignment (starts from the address which is multiplied by 4), it should be looks like the below.
0x00000000 | 0x00000004 | 0x00000008 | |||||||||
X | X | X | X |
Now, the controller or processor will fetch the data easily with the one memory cycle without doing any special work. Because the int X
is aligned properly.
If we decided to put char Z
in the memory address before the int X
, it will look like the below.
0x00000000 | 0x00000004 | 0x00000008 | |||||||||
Z | X | X | X | X |
Now, the memory is not aligned properly. What will happen if the processor or controller needs to fetch the data of int X
?
It has to read the first 4 bytes from the memory address 0x00000000
in one memory cycle and then read the memory address 0x00000004
in the second memory cycle. And it has to do some bit shifting also. If the processor or controller does this for multiple misaligned data, then it will take more time to process.
Effectively that means it will take at least two times as long as it would if the data were properly aligned. For this reason, computer scientists came up with the idea of adding padding to the data memory. So, it would be properly aligned.
In our example, adding padding after the first byte, the char
would ensure that the last part of the data would be properly aligned in memory. See the below example. (* is padding).
0x00000000 | 0x00000004 | 0x00000008 | |||||||||
Z | * | * | * | X | X | X | X |
Now, the processor or controller will directly read the 0x00000004
in one memory cycle and no bit shifting is required.
We will check this with the below example.
Example
#include <stdio.h> typedef struct { char a; // 1 byte int b; // 4 bytes } temp1; typedef struct { char a; // 1 byte int b; // 4 bytes char c; // 1 byte } temp2; int main() { printf("sizeof(structure temp) = %lu\n", sizeof(temp1)); printf("sizeof(structure temp) = %lu\n", sizeof(temp2)); return 0; }
Output
sizeof(structure temp1) = 8 sizeof(structure temp2) = 12
What do we need to do if we want to disable the structure padding?
Structure Packing in C programming
The compilers will automatically add correct padding for the target platform unless this feature is deliberately switched off. Sometimes it is required to avoid the structure padding in C. There are two ways to do that.
- Using #pragma pack(1) directive
- Using attribute
Using pragma
We can use the #pragma pack(1)
directive to avoid the structure padding. The below example disables the structure padding and reduces the wastage of memory.
#include <stdio.h> #pragma pack ( 1 ) typedef struct { char a; // 1 byte int b; // 4 bytes } temp1; typedef struct { char a; // 1 byte int b; // 4 bytes char c; // 1 byte } temp2; int main() { printf("sizeof(structure temp1) = %lu\n", sizeof(temp1)); printf("sizeof(structure temp2) = %lu\n", sizeof(temp2)); return 0; }
Output
sizeof(structure temp1) = 5 sizeof(structure temp2) = 6
Using attribute
We can use the __attribute__((packed))
in the structure declaration. Refer to the below example.
#include <stdio.h> typedef struct { char a; // 1 byte int b; // 4 bytes }__attribute__((packed)) temp1; typedef struct { char a; // 1 byte int b; // 4 bytes char c; // 1 byte }__attribute__((packed)) temp2; int main() { printf("sizeof(structure temp1) = %lu\n", sizeof(temp1)); printf("sizeof(structure temp2) = %lu\n", sizeof(temp2)); return 0; }
Output
sizeof(structure temp1) = 5 sizeof(structure temp2) = 6
Best practice
If you don’t want to use the structure packing and still want to reduce memory wastage, then you need to correctly order the structure. We need to declare members in decreasing or increasing order of size.
In the below example, we have given two structures called temp1
(members are not ordered) and temp2
(members are ordered). Check the below program and its output.
#include <stdio.h> // Members are not ordered typedef struct { char a; // 1 byte int b; // 4 bytes char c; // 1 byte } temp1; //Members are ordered typedef struct { int b; // 4 bytes char a; // 1 byte char c; // 1 byte } temp2; int main() { printf("sizeof(structure temp1) = %lu\n", sizeof(temp1)); printf("sizeof(structure temp2) = %lu\n", sizeof(temp2)); return 0; }
Output
sizeof(structure temp1) = 12 sizeof(structure temp2) = 8
We have saved 4 bytes without using the structure packing and just changing the order of the members. But still, the last two bytes are padded and we cannot avoid that. We can use this method also to reduce memory wastage.
Bit Fields in C programming
A bit field is a data structure that allows the programmer to allocate memory to structures and unions in bits in order to utilize computer memory in an efficient manner. With the implementation of bit fields, memory management becomes easy and efficient.
The need for bit field in C programming structure is,
- Easy to implement.
- Used to reduce memory consumption.
- Provides flexibility to the code
Declaration of bit fields
struct { data_type variable_name : size_in_bits; };
We will take the below example.
#include <stdio.h> struct Date { unsigned int Day; unsigned int Month; int Year; }; int main() { struct Date c = {01, 05, 2022}; printf("The date is %d / %d / %d\n", c.Day, c.Month, c.Year); printf("The size of Date is %ld bytes.\n", sizeof(struct Date)); return 0; }
The output of the program is given below.
The date is 1 / 5 / 2022 The size of Date is 12 bytes.
We know that, for a Date calendar, the range of days should be from 1 to 31, Month 1 to 12.
Day: Since the range is from 1-31, we consider 5 bits as 31 = 32 which is the nearest larger bit than the upper limit.
Month: Since the range is from 1-12, we consider 4 bits as 12 = 16 which is the nearest larger bit than the upper limit.
Year: Since the range is in four-digit like 2022, we consider 12 bits as 2022 = 2048 which is the nearest larger bit than the upper limit. You can increase this if you want to cover more years.
If we use bit fields, we can reduce some memory. Refer to the below example.
#include <stdio.h> struct Date { unsigned int Day : 5; unsigned int Month : 4; unsigned int Year : 12; }; int main() { struct Date c = {01, 05, 2022}; printf("The date is %d / %d / %d\n", c.Day, c.Month, c.Year); printf("The size of Date is %ld bytes.\n", sizeof(struct Date)); return 0; }
Output
The date is 1 / 5 / 2022 The size of Date is 4 bytes.
Limitations of bits fields
- In C programming, bit fields can not be declared as static.
- An array of bit fields does not exist and hence can not be implemented.
Nested Structure in C programming
In C programming, a nested structure refers to the concept of having a structure within another structure. This allows you to create complex data structures that contain multiple layers of information.
Here’s an example to illustrate the concept of nested structures:
#include <stdio.h> // Defining a nested structure struct Date { int day; int month; int year; }; struct Student { char name[50]; int rollNo; struct Date dob; // Nested structure as a member }; int main() { // Creating an object of the nested structure struct Student student1; // Assigning values to the nested structure members student1.rollNo = 1; student1.dob.day = 10; student1.dob.month = 5; student1.dob.year = 2000; // Accessing and displaying the nested structure members printf("Student Roll No: %d\n", student1.rollNo); printf("Date of Birth: %02d-%02d-%04d\n", student1.dob.day, student1.dob.month, student1.dob.year); return 0; }
In the above example, we define a nested structure called Date
which represents a date with day, month, and year. Then, we define another structure called Student
which includes a nested structure Date
as one of its members. This allows us to store a student’s name, roll number, and date of birth in a structured manner.
Advantages of Nested Structure
Using a nested structure in the C programming language offers several advantages:
- Modularity: Nesting structures allows you to organize related data together, making your code more modular and readable. You can define a structure within another structure to represent complex real-world relationships.
- Data Hierarchy: Nested structures enable you to represent hierarchical data structures effectively. For example, you can define a structure to represent a car, and within that structure, define another structure to represent the engine. This allows you to access and manipulate nested data easily.
- Code Reusability: By using nested structures, you can reuse existing structures as members of other structures. This helps promote code reuse and avoids duplication, resulting in cleaner and more concise code.
- Improved Data Relationships: With nested structures, you can establish relationships between different data elements. This allows you to create complex data structures that accurately represent real-world relationships, making your code more powerful and expressive.
- Encapsulation: Using nested structures provides encapsulation, allowing you to hide the implementation details of nested structures from the outside world. This enhances code maintainability, as changes made inside a structure do not impact the rest of the codebase.
- Simpler Access and Manipulation: Nested structures simplify the access and manipulation of related data. Since the nested structures are accessed using a hierarchical notation, you can easily navigate through the structure members, accessing the desired data elements.
Overall, nested structures bring organization, modularity, and flexibility to your code, allowing you to represent complex relationships and hierarchies effectively. They improve code readability, reusability, and maintainability, making them a powerful tool in C programming.
Limitation of structures
- Any function can access structure members with no data hiding.
- We can not declare a function inside the structure.
- Static members won’t be allowed to declare inside the structure.
Advantages of structure
- Using structure we are able to store data in the same memory location.
- It is helpful to access multiple data defined in structure from a single variable or pointer or pass all the structure to the function as well.
- Using an array of structures, they store more records with similar types.
Can we have a variable size of the structure where we can change the size of the structure? Yes, using flexible array members in a structure we can use the variable size. If you don’t know, please refer to this article.
Hope you have understood the concepts and in our next article, we will discuss the Union in C programming.
You can also read the below tutorials.

Embedded Software | Firmware | Linux Devic Deriver | RTOS
Hi, I’m SLR. I am a tech blogger and an Embedded Engineer. I am always eager to learn and explore tech-related concepts. And also, I wanted to share my knowledge with everyone in a more straightforward way with easy practical examples. I strongly believe that learning by doing is more powerful than just learning by reading. I love to do experiments. If you want to help or support me on my journey, consider sharing my articles, or Buy me a Coffee! Thank you for reading my blog! Happy learning!