Structures In C
Hey there! In this article, we will discuss C structures in detail, their uses, advantages, and disadvantages with examples.
-
A structure in C is a derived or user-defined data type. We use the keyword struct to define a custom data type that groups together the elements of different types. The difference between an array and a structure is that an array is a homogenous collection of similar types, whereas a structure can have elements of different types stored adjacently and identified by a name.
-
We are often required to work with values of different data types having certain relationships among them. For example, a book is described by its title (string), author (string), price (double), number of pages (integer), etc. Instead of using four different variables, these values can be stored in a single struct variable.
1. C Structure Declaration​
We have to declare structure in C before using it in our program. In structure declaration, we specify its member variables along with their datatype. We can use the struct keyword to declare the structure in C using the following syntax:
struct structure_name {
data_type member_name1;
data_type member_name1;
....
....
};
The above syntax is also called a structure template or structure prototype and no memory is allocated to the structure in the declaration
2. C Structure Definition​
A. Structure Variable Declaration with Structure​
struct structure_name {
data_type member_name1;
data_type member_name1;
....
....
}variable1, varaible2, ...;
Example​
struct book{
char title[50];
char author[50];
double price;
int pages;
} book1;
B. Structure Variable Declaration after Structure​
// structure declared beforehand
struct structure_name variable1, variable2, .......;
Example​
struct book book1;
3. Structure Initialization​
A. Initialization using Assignment Operator​
struct structure_name str;
str.member1 = value1;
str.member2 = value2;
str.member3 = value3;
.
.
.
B. Default Initialization​
By default, structure members are not automatically initialized to 0 or NULL. Uninitialized structure members will contain garbage values. However, when a structure variable is declared with an initializer, all members not explicitly initialized are zero-initialized.
struct Point
{
int x;
int y;
};
struct Point p = {0}; // Both x and y are initialized to 0
C. Initialization using Initializer List​
The initialization of a struct variable is done by placing the value of each element inside curly brackets.
Example​
struct book book1 = {"Learn C", "Dennis Ritchie", 675.50, 325};
D. Initialization using Designated Initializer List​
struct structure_name str = { .member1 = value1, .member2 = value2, .member3 = value3 };
4. Accessing the Structure Members​
We can access structure members by using the ( . ) dot operator.
Syntax​
structure_name.member1;
structure_name.member2;
Example​
#include <stdio.h>
struct book{
char title[10];
char author[20];
double price;
int pages;
};
void main(){
struct book book1 = {"Learn C", "Dennis Ritchie", 675.50, 325};
printf("Title: %s \n", book1.title);
printf("Author: %s \n", book1.author);
printf("Price: %lf\n", book1.price);
printf("Pages: %d \n", book1.pages);
printf("Size of book struct: %d", sizeof(struct book));
}
Output​
Title: Learn C
Author: Dennis Ritchie
Price: 675.500000
Pages: 325
Size of book struct: 48
In the case where we have a pointer to the structure, we can also use the arrow operator to access the members.
Syntax​
struct_pointer->title;
Example​
#include <stdio.h>
#include <string.h>
struct book{
char title[10];
char author[20];
double price;
int pages;
};
int main (){
struct book book1 = {"Learn C", "Dennis Ritchie", 675.50, 325};
struct book *strptr;
strptr = &book1;
printf("Title: %s \n", strptr -> title);
printf("Author: %s \n", strptr -> author);
printf("Price: %lf \n", strptr -> price);
printf("Pages: %d \n", strptr -> pages);
return 0;
}
Output​
Title: Learn C
Author: Dennis Ritchie
Price: 675.500000
Pages: 325
Note :​
The dot (.) operator is used to access the struct elements via the struct variable. To access the elements via its pointer, we must use the indirection (->) operator
5. typedef for Structures​
The typedef keyword is used to define an alias for the already existing datatype. In structures, we have to use the struct keyword along with the structure name to define the variables. Sometimes, this increases the length and complexity of the code. We can use the typedef to define some new shorter name for the structure.
Example​
#include <stdio.h>
// defining structure
typedef struct {
int a;
} str1;
// another way of using typedef with structures
typedef struct {
int x;
} str2;
void main()
{
// creating structure variables using new names
str1 var1 = { 20 };
str2 var2 = { 314 };
printf("var1.a = %d\n", var1.a);
printf("var2.x = %d\n", var2.x);
}
Output​
var1.a = 20
var2.x = 314
6. Bit Fields​
Bit Fields are used to specify the length of the structure members in bits. When we know the maximum length of the member, we can use bit fields to specify the size and reduce memory consumption.
Syntax​
struct structure_name {
data_type member_name: width_of_bit-field;
};
Example​
#include <stdio.h>
// declaring structure for reference
struct str1 {
int a;
char c;
};
// structure with bit fields
struct str2 {
int a : 24; // size of 'a' is 3 bytes = 24 bits
char c;
};
// driver code
int main()
{
printf("Size of Str1: %d\nSize of Str2: %d",
sizeof(struct str1), sizeof(struct str2));
return 0;
}
Output​
Size of Str1: 8
Size of Str2: 4
7. Structure Pointer in C​
We can define a pointer that points to the structure like any other variable. Such pointers are generally called Structure Pointers. We can access the members of the structure pointed by the structure pointer using the ( -> ) arrow operator.
Example​
#include <stdio.h>
// structure declaration
struct Point {
int x, y;
};
void main()
{
struct Point str = { 1, 2 };
// p2 is a pointer to structure p1
struct Point* ptr = &str;
// Accessing structure members using structure pointer
printf("%d %d", ptr->x, ptr->y);
}
Output​
1 2
Structures as Function Arguments​
You can pass a structure as a function argument in the same way as you pass any other variable or pointer.
Example​
#include <stdio.h>
#include <string.h>
struct Books{
char title[50];
char author[50];
char subject[100];
int book_id;
};
/* function declaration */
void printBook(struct Books book);
int main(){
struct Books Book1; /* Declare Book1 of type Book */
struct Books Book2; /* Declare Book2 of type Book */
/* book 1 specification */
strcpy(Book1.title, "C Programming");
strcpy(Book1.author, "Nuha Ali");
strcpy(Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* book 2 specification */
strcpy(Book2.title, "Telecom Billing");
strcpy(Book2.author, "Zara Ali");
strcpy(Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* print Book1 info */
printBook(Book1);
/* Print Book2 info */
printBook(Book2);
return 0;
}
void printBook(struct Books book){
printf("Book title : %s\n", book.title);
printf("Book author : %s\n", book.author);
printf("Book subject : %s\n", book.subject);
printf("Book book_id : %d\n", book.book_id);
}
Output​
Book title : C Programming
Book author : Nuha Ali
Book subject : C Programming Tutorial
Book book_id : 6495407
Book title : Telecom Billing
Book author : Zara Ali
Book subject : Telecom Billing Tutorial
Book book_id : 6495700
How to Pass a Struct by Reference​
In C language, a function may be defined to have its arguments passed by value or reference. A reference is the pointer to an existing variable.
Example​
#include <stdio.h>
struct rectangle{
float len, brd;
double area;
};
int area(struct rectangle *);
int main(){
struct rectangle r;
r.len = 10.50; r.brd = 20.5;
area(&r);
return 0;
}
int area(struct rectangle *r){
r -> area = (double)(r -> len * r -> brd);
printf("Length: %f \nBreadth: %f \nArea: %lf\n", r -> len, r -> brd, r -> area);
return 0;
}
Output​
Length: 10.500000
Breadth: 20.500000
Area: 215.250000
How to Return a Struct Pointer​
Example​
#include <stdio.h>
struct rectangle {
float len, brd;
double area;
};
struct rectangle * area(float x, float y);
int main (){
struct rectangle *r;
float x, y;
x = 10.5; y = 20.5;
r = area(x, y);
printf("Length: %f \n Breadth: %f \n Area: %lf\n", r->len, r->brd, r->area);
return 0;
}
struct rectangle * area(float x, float y){
double area = (double)(x*y);
static struct rectangle r;
r.len = x; r.brd = y; r.area = area;
return &r;
}
Output​
Length: 10.500000
Breadth: 20.500000
Area: 215.250000
8. Self-Referential Structures​
The self-referential structures in C are those structures that contain references to the same type as themselves i.e. they contain a member of the type pointer pointing to the same structure type.
Example​
struct structure_name {
data_type member1;
data_type member2;
struct structure_name* str;
}
// C program to illustrate the self referential structures
#include <stdio.h>
// structure template
typedef struct str {
int mem1;
int mem2;
struct str* next;
}str;
// driver code
int main()
{
str var1 = { 1, 2, NULL };
str var2 = { 10, 20, NULL };
// assigning the address of var2 to var1.next
var1.next = &var2;
// pointer to var1
str *ptr1 = &var1;
// accessing var2 members using var1
printf("var2.mem1: %d\nvar2.mem2: %d", ptr1->next->mem1,
ptr1->next->mem2);
return 0;
}
Output​
var2.mem1: 10
var2.mem2: 20
9. Array of Structures in C​
In C programming, the struct keyword is used to define a derived data type. Once defined, you can declare an array of struct variables, just like an array of int, float or char types is declared. An array of structures has a number of use-cases such as in storing records similar to a database table where you have each row with different data types.
Usually, a struct type is defined at the beginning of the code so that its type can be used inside any of the functions. You can declare an array of structures and later on fill data in it or you can initialize it at the time of declaration itself.
Initializing a Struct Array​
Example​
struct book{
char title[10];
double price;
int pages;
};
struct book b[3] = {
{"Learn C", 650.50, 325},
{"C Pointers", 175, 225},
{"C Pearls", 250, 250}
};
Declaring a Struct Array​
Example​
struct book b[3];
strcpy(b[0].title, "Learn C");
b[0].price = 650.50;
b[0].pages=325;
strcpy(b[1].title, "C Pointers");
b[1].price = 175;
b[1].pages=225;
strcpy(b[2].title, "C Pearls");
b[2].price = 250;250
b[2].pages=325;
Reading a Struct Array​
Example​
#include <stdio.h>
struct book{
char title[10];
double price;
int pages;
};
int main(){
struct book b[3];
strcpy(b[0].title, "Learn C");
b[0].price = 650.50;
b[0].pages = 325;
strcpy(b[1].title, "C Pointers");
b[1].price = 175;
b[1].pages = 225;
strcpy(b[2].title, "C Pearls");
b[2].price = 250;
b[2].pages = 325;
printf("\nList of Books:\n");
for (int i = 0; i < 3; i++){
printf("Title: %s \tPrice: %7.2lf \tPages: %d\n", b[i].title, b[i].price, b[i].pages);
}
return 0;
}
Output​
List of Books:
Title: Learn C Price: 650.50 Pages: 325
Title: C Pointers Price: 175.00 Pages: 225
Title: C Pearls Price: 250.00 Pages: 325
10. Difference between Structures & Unions in C​
Structures in C is a user-defined data type available in C that allows to combining of data items of different kinds. Structures are used to represent a record.
Defining a structure: To define a structure, you must use the struct statement. The struct statement defines a new data type, with more than or equal to one member. The format of the struct statement is as follows:
struct [structure name]
{
member definition;
member definition;
...
member definition;
};
(OR)
struct [structure name]
{
member definition;
member definition;
...
member definition;
}structure variable declaration;
Union in C is a special data type available in C that allows storing different data types in the same memory location. You can define a union with many members, but only one member can contain a value at any given time. Unions provide an efficient way of using the same memory location for multiple purposes.
Defining a Union: To define a union, you must use the union statement in the same way as you did while defining a structure. The union statement defines a new data type with more than one member for your program. The format of the union statement is as follows:
union [union name]
{
member definition;
member definition;
...
member definition;
};
(OR)
union [union name]
{
member definition;
member definition;
...
member definition;
}union variable declaration;
Similarities Between Structure and Union​
- Both are user-defined data types used to store data of different types as a single unit. Their members can be objects of any type, including other structures and unions or arrays. A member can also consist of a bit field.
- Both structures and unions support only assignment = and sizeof operators. The two structures or unions in the assignment must have the same members and member types.
- A structure or a union can be passed by value to functions and returned by value by functions. The argument must have the same type as the function parameter. A structure or union is passed by value just like a scalar variable as a corresponding parameter.
- '.' operator or selection operator, which has one of the highest precedences, is used for accessing member variables inside both the user-defined datatypes.
Differences between Structure and Union​
a. Memory Allocation​
- Structures: Each member of a structure has its own memory location. The total memory allocated is the sum of the memory required for each member.
- Unions: All members share the same memory location. The memory allocated is equal to the size of the largest member. Only one member can hold a value at any given time.
b. Accessing Members​
- Structures: All members can be accessed simultaneously because they have separate memory.
- Unions: Only one member's value is valid at a time, as all members share the same memory location.
c. Use cases​
- Structures: Used when multiple values are needed at the same time, such as data collections where all attributes are relevant.
- Unions: Useful when a variable may hold multiple data types but only one at a time, such as in cases involving memory or space constraints, like implementing a variant data type.
d. Initialization and Assignment​
- Structures: Can be initialized with multiple values for all members.
- Unions: Can be initialized with only one member at a time.
Example​
Let's consider a scenario where we have a structure to represent an employee's details, which includes a union for a field that may store different types of IDs (e.g., an integer employee ID, a string for government ID, or a floating-point ID for a special category).
#include <stdio.h>
#include <string.h>
// Define a union for multiple types of IDs
union ID {
int empID;
char govID[20];
float specialID;
};
// Define a structure that includes the union along with other employee details
struct Employee {
char name[50];
int age;
float salary;
union ID id; // Union for storing one type of ID at a time
int idType; // 1 for empID, 2 for govID, 3 for specialID
};
int main() {
struct Employee emp;
// Set up employee details
strcpy(emp.name, "Alice");
emp.age = 30;
emp.salary = 75000.0;
// Example 1: Using empID
emp.idType = 1; // Set ID type
emp.id.empID = 12345;
printf("Employee Details:\n");
printf("Name: %s\n", emp.name);
printf("Age: %d\n", emp.age);
printf("Salary: %.2f\n", emp.salary);
if (emp.idType == 1) {
printf("Employee ID: %d\n", emp.id.empID);
}
// Example 2: Using govID (overwrites empID)
emp.idType = 2;
strcpy(emp.id.govID, "A12345XYZ");
printf("\nUsing Government ID:\n");
printf("Name: %s\n", emp.name);
if (emp.idType == 2) {
printf("Government ID: %s\n", emp.id.govID);
}
// Example 3: Using specialID (overwrites govID)
emp.idType = 3;
emp.id.specialID = 4567.89;
printf("\nUsing Special ID:\n");
printf("Name: %s\n", emp.name);
if (emp.idType == 3) {
printf("Special ID: %.2f\n", emp.id.specialID);
}
return 0;
}
Explanation​
-
Employee Structure: The Employee structure contains standard information about the employee (e.g., name, age, salary) and a union, ID, for storing one type of identifier at a time.
-
ID Union: The union ID can store an integer employee ID (empID), a government ID as a string (govID), or a floating-point special ID (specialID).
-
ID Type Indicator: The idType field is used to keep track of which type of ID is currently stored in the union.
Output​
The output will show different details depending on which type of ID is used. Only one type of ID is active at any time because all members in the union share the same memory.
Employee Details:
Name: Alice
Age: 30
Salary: 75000.00
Employee ID: 12345
Using Government ID:
Name: Alice
Government ID: A12345XYZ
Using Special ID:
Name: Alice
Special ID: 4567.89
This example demonstrates:
- Structure fields (name, age, salary) remain consistent across all cases.
- Union fields show different IDs based on idType, illustrating how unions allow only one active value at a time.
11. Differences between Structure and Arrays in C​
1. Data Type of Elements​
- Structures: Can contain elements (members) of different data types. Each member can be of any type, including other structures.
- Arrays: All elements must be of the same data type (e.g., all int, all float, etc.).
2. Memory Allocation​
- Structures: Each member has its own memory space, and the total size is the sum of all member sizes (with potential padding for alignment).
- Arrays: A contiguous block of memory is allocated for all elements, where the total size is the size of one element multiplied by the number of elements.
3. Accessing Elements​
- Structures: Members are accessed by name using the dot (.) operator with the structure variable.
- Arrays: Elements are accessed using an index inside square brackets ([]), with indices starting at 0.
4. Homogeneous vs. Heterogeneous Data​
- Structures: Used for heterogeneous data, where different types of information are grouped together (e.g., name, age, and height of a person).
- Arrays: Used for homogeneous data, where all elements are of the same type, like a list of scores.
5. Usage​
- Structures: Commonly used to represent a complex data entity, like a student, employee, or product, where various attributes are combined.
- Arrays: Typically used for lists, sequences, or collections of data items of the same type.
6. Initialization​
- Structures: Can initialize each member individually.
- Arrays: Can initialize elements in a list using notation.
Example​
#include <stdio.h>
struct Person {
char name[50];
int age;
float height;
};
int main() {
struct Person people[2] = {
{"Alice", 25, 5.6},
{"Bob", 30, 6.1}
};
printf("Name: %s, Age: %d, Height: %.1f\n", people[0].name, people[0].age, people[0].height);
printf("Name: %s, Age: %d, Height: %.1f\n", people[1].name, people[1].age, people[1].height);
return 0;
}
In this example, "people" is an array of 'Person' structures, allowing you to store multiple persons and access each one's details separately.
Output​
Name: Alice, Age: 25, Height: 5.6
Name: Bob, Age: 30, Height: 6.1
12. Uses of Structure in C​
C structures are used for the following:
- The structure can be used to define the custom data types that can be used to create some complex data types such as dates, time, complex numbers, etc. which are not present in the language.
- It can also be used in data organization where a large amount of data can be stored in different fields.
- Structures are used to create data structures such as trees, linked lists, etc.
- They can also be used for returning multiple values from a function.
13. Limitations of C Structures​
In C language, structures provide a method for packing together data of different types. A Structure is a helpful tool to handle a group of logically related data items. However, C structures also have some limitations.
- Higher Memory Consumption: It is due to structure padding.
- No Data Hiding: C Structures do not permit data hiding. Structure members can be accessed by any function, anywhere in the scope of the structure.
- Functions inside Structure: C structures do not permit functions inside the structure so we cannot provide the associated functions.
- Static Members: C Structure cannot have static members inside its body. Construction creation in Structure: Structures in C cannot have a constructor inside Structures.
14. Conclusion​
In conclusion, structures in C enhance the language's capabilities to handle complex data, making it versatile for a wide range of applications. Proper use of structures not only optimizes memory management but also improves the overall design and functionality of C-based software.