Virtual assistance

C Programming Tutorial

Welcome to AIVista --India's tutorial pages on C Programming

C Programming

Structures in C

Structures allow you to group variables of different data types under a single name, creating user-defined data types.

"A structure is a user-defined data type that allows you to combine data items of different kinds."

What is a Structure?

A structure is a user-defined data type that allows grouping of variables of different data types under a single name. Structures are used to represent records or collections of related data.

Defining a Structure

Basic Structure Definition

// Structure definition
struct structure_name {
    data_type member1;
    data_type member2;
    // ... more members
};

// Example: Student structure
struct Student {
    int roll_number;
    char name[50];
    float marks;
    char grade;
};

Structure Variable Declaration

// Method 1: Declare after definition
struct Student student1, student2;

// Method 2: Declare with definition
struct Employee {
    int id;
    char name[50];
    float salary;
} emp1, emp2;

// Method 3: Using typedef (creates alias)
typedef struct {
    int day;
    int month;
    int year;
} Date;

Date today, birthday;

Accessing Structure Members

Structure members are accessed using the dot (.) operator.

Basic Member Access

#include <stdio.h>
#include <string.h>

struct Student {
    int roll_number;
    char name[50];
    float marks;
};

int main() {
    struct Student s1;

    // Assign values to members
    s1.roll_number = 101;
    strcpy(s1.name, "John Doe");
    s1.marks = 85.5;

    // Access and display members
    printf("Roll Number: %d\n", s1.roll_number);
    printf("Name: %s\n", s1.name);
    printf("Marks: %.2f\n", s1.marks);

    return 0;
}

Structure Initialization

#include <stdio.h>
#include <string.h>

struct Student {
    int roll_number;
    char name[50];
    float marks;
};

int main() {
    // Method 1: Initialize during declaration
    struct Student s1 = {101, "Alice", 92.5};

    // Method 2: Designated initialization (C99)
    struct Student s2 = {
        .roll_number = 102,
        .name = "Bob",
        .marks = 88.0
    };

    // Method 3: Partial initialization (remaining members set to 0)
    struct Student s3 = {103, "Charlie"};

    printf("Student 1: %d, %s, %.2f\n", s1.roll_number, s1.name, s1.marks);
    printf("Student 2: %d, %s, %.2f\n", s2.roll_number, s2.name, s2.marks);
    printf("Student 3: %d, %s, %.2f\n", s3.roll_number, s3.name, s3.marks);

    return 0;
}

Array of Structures

#include <stdio.h>
#include <string.h>

struct Student {
    int roll_number;
    char name[50];
    float marks;
};

int main() {
    struct Student students[3];

    // Initialize array of structures
    for (int i = 0; i < 3; i++) {
        printf("Enter details for student %d:\n", i + 1);
        printf("Roll Number: ");
        scanf("%d", &students[i].roll_number);
        printf("Name: ");
        scanf("%s", students[i].name);
        printf("Marks: ");
        scanf("%f", &students[i].marks);
    }

    // Display all students
    printf("\nStudent Details:\n");
    for (int i = 0; i < 3; i++) {
        printf("Student %d: %d, %s, %.2f\n",
               i + 1, students[i].roll_number,
               students[i].name, students[i].marks);
    }

    return 0;
}

Structure Pointers

You can create pointers to structures and access members using the arrow (->) operator.

Structure Pointers

#include <stdio.h>
#include <string.h>

struct Student {
    int roll_number;
    char name[50];
    float marks;
};

int main() {
    struct Student s1 = {101, "Alice", 92.5};
    struct Student *ptr = &s1;

    // Access members using pointer
    printf("Roll Number: %d\n", ptr->roll_number);
    printf("Name: %s\n", ptr->name);
    printf("Marks: %.2f\n", ptr->marks);

    // Modify members using pointer
    ptr->marks = 95.0;
    printf("Updated Marks: %.2f\n", ptr->marks);

    return 0;
}

Dynamic Memory Allocation for Structures

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Student {
    int roll_number;
    char name[50];
    float marks;
};

int main() {
    struct Student *ptr;

    // Allocate memory for structure
    ptr = (struct Student*)malloc(sizeof(struct Student));

    if (ptr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }

    // Assign values
    ptr->roll_number = 101;
    strcpy(ptr->name, "Dynamic Student");
    ptr->marks = 87.5;

    // Display values
    printf("Roll Number: %d\n", ptr->roll_number);
    printf("Name: %s\n", ptr->name);
    printf("Marks: %.2f\n", ptr->marks);

    // Free allocated memory
    free(ptr);

    return 0;
}

Nested Structures

Structures can contain other structures as members.

Basic Nested Structures

#include <stdio.h>
#include <string.h>

struct Address {
    char street[50];
    char city[30];
    char state[30];
    int pincode;
};

struct Employee {
    int id;
    char name[50];
    struct Address addr;
    float salary;
};

int main() {
    struct Employee emp;

    // Assign values
    emp.id = 1001;
    strcpy(emp.name, "John Smith");
    strcpy(emp.addr.street, "123 Main St");
    strcpy(emp.addr.city, "New York");
    strcpy(emp.addr.state, "NY");
    emp.addr.pincode = 10001;
    emp.salary = 50000.0;

    // Display values
    printf("Employee ID: %d\n", emp.id);
    printf("Name: %s\n", emp.name);
    printf("Address: %s, %s, %s - %d\n",
           emp.addr.street, emp.addr.city,
           emp.addr.state, emp.addr.pincode);
    printf("Salary: %.2f\n", emp.salary);

    return 0;
}

Structure within Structure Pointer

#include <stdio.h>
#include <string.h>

struct Date {
    int day, month, year;
};

struct Person {
    char name[50];
    struct Date birth_date;
};

int main() {
    struct Person person;
    struct Person *ptr = &person;

    // Assign values using pointer
    strcpy(ptr->name, "Alice Johnson");
    ptr->birth_date.day = 15;
    ptr->birth_date.month = 8;
    ptr->birth_date.year = 1995;

    // Display values
    printf("Name: %s\n", ptr->name);
    printf("Birth Date: %d/%d/%d\n",
           ptr->birth_date.day,
           ptr->birth_date.month,
           ptr->birth_date.year);

    return 0;
}

Structure Padding and Packing

Structures may have padding bytes for memory alignment.

Structure Size and Padding

#include <stdio.h>

struct Example {
    char c;      // 1 byte
    int i;       // 4 bytes
    char c2;     // 1 byte
};

int main() {
    struct Example ex;

    printf("Size of char: %lu bytes\n", sizeof(char));
    printf("Size of int: %lu bytes\n", sizeof(int));
    printf("Size of structure: %lu bytes\n", sizeof(struct Example));

    // Structure may have padding for alignment
    printf("Address of c: %p\n", &ex.c);
    printf("Address of i: %p\n", &ex.i);
    printf("Address of c2: %p\n", &ex.c2);

    return 0;
}

typedef with Structures

typedef creates aliases for structure types, making code cleaner.

Using typedef with Structures

#include <stdio.h>
#include <string.h>

// Method 1: typedef with struct
typedef struct {
    int x, y;
} Point;

// Method 2: typedef with named struct
typedef struct Rectangle {
    Point top_left;
    int width, height;
} Rectangle;

int main() {
    Point p1 = {10, 20};
    Rectangle rect = {{0, 0}, 100, 50};

    printf("Point: (%d, %d)\n", p1.x, p1.y);
    printf("Rectangle: Top-left(%d, %d), Width: %d, Height: %d\n",
           rect.top_left.x, rect.top_left.y,
           rect.width, rect.height);

    return 0;
}

Passing Structures to Functions

Pass by Value

#include <stdio.h>
#include <string.h>

struct Student {
    int roll_number;
    char name[50];
    float marks;
};

// Pass by value (creates copy)
void displayStudent(struct Student s) {
    printf("Roll: %d, Name: %s, Marks: %.2f\n",
           s.roll_number, s.name, s.marks);
}

int main() {
    struct Student s1 = {101, "Alice", 92.5};
    displayStudent(s1);
    return 0;
}

Pass by Reference

#include <stdio.h>
#include <string.h>

struct Student {
    int roll_number;
    char name[50];
    float marks;
};

// Pass by reference (modifies original)
void updateMarks(struct Student *s, float new_marks) {
    s->marks = new_marks;
}

int main() {
    struct Student s1 = {101, "Alice", 92.5};

    printf("Before update: %.2f\n", s1.marks);
    updateMarks(&s1, 95.0);
    printf("After update: %.2f\n", s1.marks);

    return 0;
}

Bit Fields in Structures

Bit fields allow packing of data in structures at the bit level.

Bit Field Example

#include <stdio.h>

struct Flags {
    unsigned int flag1 : 1;  // 1 bit
    unsigned int flag2 : 1;  // 1 bit
    unsigned int flag3 : 1;  // 1 bit
    unsigned int data : 5;   // 5 bits
};

int main() {
    struct Flags f;

    f.flag1 = 1;
    f.flag2 = 0;
    f.flag3 = 1;
    f.data = 15;  // 5-bit value (0-31)

    printf("Size of structure: %lu bytes\n", sizeof(struct Flags));
    printf("Flags: %d, %d, %d, Data: %d\n",
           f.flag1, f.flag2, f.flag3, f.data);

    return 0;
}

Practical Examples

1. Student Management System

#include <stdio.h>
#include <string.h>

#define MAX_STUDENTS 100

struct Student {
    int roll_number;
    char name[50];
    float marks[5];  // marks in 5 subjects
    float average;
    char grade;
};

void calculateGrade(struct Student *s) {
    s->average = 0;
    for (int i = 0; i < 5; i++) {
        s->average += s->marks[i];
    }
    s->average /= 5;

    if (s->average >= 90) s->grade = 'A';
    else if (s->average >= 80) s->grade = 'B';
    else if (s->average >= 70) s->grade = 'C';
    else if (s->average >= 60) s->grade = 'D';
    else s->grade = 'F';
}

int main() {
    struct Student students[MAX_STUDENTS];
    int n;

    printf("Enter number of students: ");
    scanf("%d", &n);

    for (int i = 0; i < n; i++) {
        printf("\nEnter details for student %d:\n", i + 1);
        printf("Roll Number: ");
        scanf("%d", &students[i].roll_number);
        printf("Name: ");
        scanf("%s", students[i].name);

        printf("Enter marks in 5 subjects: ");
        for (int j = 0; j < 5; j++) {
            scanf("%f", &students[i].marks[j]);
        }

        calculateGrade(&students[i]);
    }

    // Display results
    printf("\nStudent Report:\n");
    printf("Roll\tName\t\tAverage\tGrade\n");
    for (int i = 0; i < n; i++) {
        printf("%d\t%s\t\t%.2f\t%c\n",
               students[i].roll_number,
               students[i].name,
               students[i].average,
               students[i].grade);
    }

    return 0;
}

Advantages of Structures

  • Group related data together
  • Create user-defined data types
  • Improve code organization and readability
  • Enable complex data representations
  • Support for nested structures

Limitations of Structures

  • Structure padding can waste memory
  • No built-in methods or functions
  • Data hiding is not supported
  • Operator overloading is not possible

Best Practices

  • Use meaningful structure names and member names
  • Consider memory alignment and padding
  • Use typedef for cleaner code
  • Pass structures by reference to functions when modifying
  • Initialize structure members properly
  • Document the purpose and usage of structures

Conclusion

Structures are fundamental to organizing complex data in C programs. They allow you to create custom data types that group related information together. Mastering structures is essential for building real-world applications. Practice creating and using different types of structures to become proficient! 🚀