C Structures
Structures in C are one of the most powerful features of the language that allow programmers to create custom data types by grouping variables of different data types together. They provide a way to organize related data elements, making your code more organized and readable.
What Are Structures?
A structure in C is a composite data type that defines a grouped list of variables to be placed under one name in a block of memory. These variables, known as members, can have different data types and are allocated memory in sequential order.
struct Student {
    char name[50];
    int roll_number;
    float marks;
};
In this example, Student is a structure containing three members: name, roll_number, and marks.
Defining a Structure
The general syntax for defining a structure is:
struct tag_name {
    data_type member1;
    data_type member2;
    ...
    data_type memberN;
};
Where:
- tag_nameis the name of the structure (optional)
- member1,- member2, etc. are the member variables
- Each member can have any valid C data type (including other structures)
Declaring Structure Variables
You can declare structure variables in several ways:
Method 1: After Structure Definition
struct Student {
    char name[50];
    int roll_number;
    float marks;
};
struct Student student1, student2;  // Declaring two variables of type struct Student
Method 2: During Structure Definition
struct Student {
    char name[50];
    int roll_number;
    float marks;
} student1, student2;
Method 3: Using Typedef
typedef struct {
    char name[50];
    int roll_number;
    float marks;
} Student;
Student student1, student2;  // No need for 'struct' keyword
Accessing Structure Members
To access the members of a structure, we use the dot operator (.):
student1.roll_number = 101;
strcpy(student1.name, "John Doe");
student1.marks = 91.5;
printf("Student Name: %s\n", student1.name);
printf("Roll Number: %d\n", student1.roll_number);
printf("Marks: %.2f\n", student1.marks);
Structure Initialization
Structures can be initialized in different ways:
Method 1: Member-by-Member
struct Student student1;
strcpy(student1.name, "John Doe");
student1.roll_number = 101;
student1.marks = 91.5;
Method 2: Using Initializer List
struct Student student1 = {"John Doe", 101, 91.5};
Method 3: Designated Initializers (C99 and later)
struct Student student1 = {
    .name = "John Doe",
    .roll_number = 101,
    .marks = 91.5
};
Structures and Functions
Passing Structures to Functions
You can pass structures to functions by value or by reference:
Pass by Value
void displayStudent(struct Student s) {
    printf("Name: %s\n", s.name);
    printf("Roll Number: %d\n", s.roll_number);
    printf("Marks: %.2f\n", s.marks);
}
// Function call
displayStudent(student1);
Pass by Reference
void updateMarks(struct Student *s, float new_marks) {
    s->marks = new_marks;  // Using arrow operator
}
// Function call
updateMarks(&student1, 95.0);
When passing structures by reference, we use the arrow operator (->) to access structure members.
Returning Structures from Functions
struct Student createStudent(char name[], int roll, float marks) {
    struct Student temp;
    strcpy(temp.name, name);
    temp.roll_number = roll;
    temp.marks = marks;
    return temp;
}
// Function call
struct Student newStudent = createStudent("Jane Doe", 102, 89.5);
Structure Pointers
A pointer to a structure can be declared and used as follows:
struct Student *ptr_student;
ptr_student = &student1;
// Accessing members using pointer
printf("Name: %s\n", ptr_student->name);
printf("Roll Number: %d\n", ptr_student->roll_number);
The arrow operator (->) is used to access structure members via a pointer.
Nested Structures
Structures can contain other structures as members:
struct Date {
    int day;
    int month;
    int year;
};
struct Student {
    char name[50];
    int roll_number;
    struct Date dob;  // Nested structure
};
// Usage
struct Student student1;
student1.dob.day = 15;
student1.dob.month = 8;
student1.dob.year = 2000;
Self-Referential Structures
A structure that contains a pointer to the same structure type is called a self-referential structure:
struct Node {
    int data;
    struct Node *next;  // Pointer to the same structure type
};
This is the foundation for linked data structures like linked lists, trees, and graphs.
Memory Padding and Structure Packing
The C compiler may add padding between structure members to ensure proper memory alignment:
struct Example {
    char c;     // 1 byte
    // 3 bytes padding might be added here
    int i;      // 4 bytes
    char d;     // 1 byte
    // 3 bytes padding might be added here
};
To control padding, you can use compiler-specific directives like #pragma pack or use the attribute __attribute__((packed)) in GCC.
Practical Example
Let's put everything together with a practical example:
#include <stdio.h>
#include <string.h>
struct Address {
    char street[50];
    char city[30];
    int zip;
};
struct Employee {
    int id;
    char name[50];
    float salary;
    struct Address addr;
};
void displayEmployee(struct Employee emp) {
    printf("Employee ID: %d\n", emp.id);
    printf("Name: %s\n", emp.name);
    printf("Salary: $%.2f\n", emp.salary);
    printf("Address: %s, %s - %d\n", 
           emp.addr.street, emp.addr.city, emp.addr.zip);
}
int main() {
    struct Employee emp1 = {
        .id = 1001,
        .name = "John Smith",
        .salary = 75000.0,
        .addr = {
            .street = "123 Main St",
            .city = "Boston",
            .zip = 02115
        }
    };
    
    displayEmployee(emp1);
    
    return 0;
}
Best Practices
- Use meaningful names for structures and their members
- Consider using typedef to create more readable code
- Be aware of memory alignment and padding in performance-critical applications
- When passing large structures to functions, use pointers to avoid unnecessary copying
- Initialize structures properly to avoid undefined behavior
- Use designated initializers (C99) for better readability
Summary
Structures in C provide a powerful way to create custom data types by grouping related data items together. They are essential for creating complex data structures and organizing your code in a meaningful way. Understanding structures is crucial for advanced C programming and is a foundation for object-oriented concepts in other languages.
💡 Found a typo or mistake? Click "Edit this page" to suggest a correction. Your feedback is greatly appreciated!