C Self-Referential Structures, Binary File I/O & 5 Production Projects
Welcome to Phase 11 (Chapter 29): C Self-Referential Structures, Binary File I/O & 5 Production Projects Masterclass! Beyond basic data grouping, structures are the foundation for complex dynamic data structures (Linked Lists, Binary Trees, Graphs) and persistent file databases. In this exhaustive textbook-grade guide, you will master Self-Referential Structures containing pointers to their own type, learn how to serialize entire structure records directly to disk using Binary File I/O (fwrite / fread), and build 5 complete production-ready software systems.
A Self-Referential Structure contains a pointer member that points to an instance of the same structure type:
Node 1 (Address: 0x1000) Node 2 (Address: 0x2000) Node 3 (Address: 0x3000)
โโโโโโโโโโโโฌโโโโโโโโโโโโ โโโโโโโโโโโโฌโโโโโโโโโโโโ โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ Data: 10 โ Next:0x200โ โโโโโบ โ Data: 20 โ Next:0x300โ โโโโโบ โ Data: 30 โ Next: NULLโ
โโโโโโโโโโโโดโโโโโโโโโโโโ โโโโโโโโโโโโดโโโโโโโโโโโโ โโโโโโโโโโโโดโโโโโโโโโโโโ
struct Node {
int data;
struct Node* next; // Self-referential pointer!
};
Instead of formatting structures into text using fprintf, C allows writing raw RAM memory bytes of a structure directly to a binary file (.dat) using fwrite() and reading them back instantly using fread():
โก Binary Struct Serialization Commands:
โข Write: fwrite(&student, sizeof(struct Student), 1, filePtr);
โข Read: fread(&student, sizeof(struct Student), 1, filePtr);
๐ Overview of Included Production Systems:
1. Student Management System: Add, search by Roll No, update marks, and calculate CGPA.
2. Employee Records Database: Track ID, Department, Salary, and filter by salary range.
3. Product Inventory Manager: Stock tracking, unit price calculation, and re-order alerts.
4. Library Management System: Book ISBN search, issue/return status, and author filtering.
5. Contact Book Engine: Name, Phone Number, Email lookup with file persistence.
#include <stdio.h>
#include <string.h>
typedef struct {
int rollNo;
char name[40];
float gpa;
} StudentRecord;
void printStudent(const StudentRecord *s) {
printf("Roll: %d | Name: %s | GPA: %.2f\n", s->rollNo, s->name, s->gpa);
}
int main(void) {
StudentRecord classRoster[3] = {
{101, "Ravi Kumar", 3.85f},
{102, "Anita Roy", 3.92f},
{103, "Suresh P", 3.65f}
};
printf("=== STUDENT MANAGEMENT SYSTEM ROSTER ===\n");
for (int i = 0; i < 3; i++) {
printStudent(&classRoster[i]);
}
return 0;
}
Q1: Why must self-referential structures use pointer members (struct Node* next) instead of direct instances (struct Node next)?
If a struct contained a direct instance of itself, its size would be infinite (recursive memory embedding), causing a compilation error. A pointer member has a fixed size (8 bytes on 64-bit OS), making the struct size finite and well-defined!
Q2: Is binary struct file I/O portable across different computers?
Not always! Binary files written on a Little-Endian system (x86/ARM) or systems with different compiler padding alignment might not read back correctly on Big-Endian systems or systems compiled with different #pragma pack rules.
Run this contact record manager in our live GCC compiler:
#include <stdio.h>
typedef struct {
char name[30];
char phone[15];
} Contact;
int main(void) {
Contact c = {"Balanju Support", "+91-9876543210"};
printf("Contact: %s (%s)\n", c.name, c.phone);
return 0;
}