Structures, Files & More
Structures, Unions & Enums
Group related data with struct, name types with typedef, use arrays of structures and pointers to them, and compare structures with unions and enums.
Real things have several properties. A student has a roll number, a name and a CGPA. A structure (struct) bundles variables of different types into one new type.
#include <stdio.h>
#include <string.h>
struct Student {
int roll;
char name[30];
float cgpa;
};
int main(void) {
struct Student s1 = {101, "Asha Rao", 9.1f};
struct Student s2;
s2.roll = 102; // the dot operator accesses members
strcpy(s2.name, "Ravi Kumar");
s2.cgpa = 8.4f;
printf("%d %-12s %.1f\n", s1.roll, s1.name, s1.cgpa);
printf("%d %-12s %.1f\n", s2.roll, s2.name, s2.cgpa);
return 0;
}101 Asha Rao 9.1 102 Ravi Kumar 8.4
typedef
typedef gives a type a shorter name, so you can write Student instead of struct Student:
#include <stdio.h>
typedef struct {
double x, y;
} Point;
double area(Point a, Point b, Point c) { // triangle area from three corners
double v = (a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)) / 2;
return v < 0 ? -v : v;
}
int main(void) {
Point a = {0, 0}, b = {4, 0}, c = {0, 3};
printf("Area = %.1f\n", area(a, b, c));
return 0;
}Area = 6.0
Arrays of structures
#include <stdio.h>
typedef struct {
int roll;
char name[20];
int marks;
} Student;
int main(void) {
Student cls[50];
int n, top = 0;
printf("How many students? ");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
printf("Roll, name, marks: ");
scanf("%d %19s %d", &cls[i].roll, cls[i].name, &cls[i].marks);
if (cls[i].marks > cls[top].marks) top = i;
}
printf("Topper: %s (roll %d) with %d marks\n", cls[top].name, cls[top].roll, cls[top].marks);
return 0;
}How many students? 3 Roll, name, marks: 1 Asha 88 Roll, name, marks: 2 Ravi 95 Roll, name, marks: 3 Meera 79 Topper: Ravi (roll 2) with 95 marks
Pointers to structures and the arrow operator
With a pointer to a struct, use -> to reach a member. p->marks is shorthand for (*p).marks:
#include <stdio.h>
typedef struct {
char name[20];
int balance;
} Account;
void deposit(Account *acc, int amount) { // pass by pointer: no copy, changes stick
acc->balance += amount;
}
int main(void) {
Account a = {"Priya", 500};
Account *p = &a;
deposit(p, 250);
printf("%s has Rs %d\n", p->name, p->balance);
printf("Same thing: %d\n", (*p).balance);
return 0;
}Priya has Rs 750 Same thing: 750
Passing a pointer to a large struct is faster than passing the struct itself, because nothing is copied.
Nested structures
#include <stdio.h>
typedef struct { int day, month, year; } Date;
typedef struct { char title[40]; Date due; } Assignment;
int main(void) {
Assignment a = {"Linked list lab", {14, 11, 2026}};
printf("%s is due on %02d/%02d/%d\n", a.title, a.due.day, a.due.month, a.due.year);
return 0;
}Linked list lab is due on 14/11/2026
Structure size and padding
The compiler may insert unused padding bytes so each member starts at an address the CPU can read quickly. So a struct can be bigger than the sum of its members:
#include <stdio.h>
struct A { char c; int i; char d; }; // 1 + (3 pad) + 4 + 1 + (3 pad) = 12
struct B { int i; char c; char d; }; // 4 + 1 + 1 + (2 pad) = 8
int main(void) {
printf("sizeof(struct A) = %zu\n", sizeof(struct A));
printf("sizeof(struct B) = %zu\n", sizeof(struct B));
return 0;
}sizeof(struct A) = 12 sizeof(struct B) = 8
Unions
A union looks like a struct, but all its members share the same memory. Its size is the size of its largest member, and only one member holds a meaningful value at a time.
#include <stdio.h>
union Value {
int i;
float f;
char c;
};
int main(void) {
union Value v;
printf("sizeof(union Value) = %zu\n", sizeof(v));
v.i = 65;
printf("as int: %d, as char: %c\n", v.i, v.c); // same bytes, read as a char
v.f = 3.5f; // overwrites the int
printf("as float: %.1f\n", v.f);
return 0;
}sizeof(union Value) = 4 as int: 65, as char: A as float: 3.5
| Structure | Union |
|---|---|
| Each member has its own memory | All members share one memory location |
| Size ≥ sum of member sizes | Size = largest member (plus padding) |
| All members usable at once | Only the last written member is valid |
Enumerations
An enum gives names to integer constants, which makes code self-explanatory:
#include <stdio.h>
enum Day { MON = 1, TUE, WED, THU, FRI, SAT, SUN }; // TUE = 2, WED = 3 ...
int main(void) {
enum Day today = FRI;
printf("Friday is day %d\n", today);
if (today == SAT || today == SUN) printf("Weekend!\n");
else printf("%d day(s) to the weekend\n", SAT - today);
return 0;
}Friday is day 5 1 day(s) to the weekend
Test yourself
4 questions · pick an answer to check it instantly
- 1
Given
struct Student *p;, how do you access therollmember?->dereferences the pointer and selects the member; it equals(*p).roll.*p.rollparses as*(p.roll). - 2
What is the size of
union { int i; double d; char c; }on a typical 64-bit machine?A union is as large as its largest member, here the 8-bytedouble. - 3
Why might
sizeof(struct { char a; int b; })be 8 instead of 5?Alignment padding is inserted aftera. - 4
In
enum Color { RED, GREEN = 5, BLUE };what isBLUE?Enumerators count up from the previous value:GREENis 5, soBLUEis 6.