Skip to content

Intermediate · Structs, unions, enums and files · topic 31 of 60 · 25 min

Structs

Explanation

A struct groups variables of different types into one record, such as a student with a name, a roll number and marks. Access members with the dot operator (s.roll). Designated initialisers (.roll = 7) make initialisation clear. Structs can be copied with = and passed to or returned from functions by value. typedef gives the type a shorter name.

Why structs?

A student has a name, a roll number and marks. Keeping them in three parallel arrays (names[i], rolls[i], marks[i]) is fragile: sort one array and forget the others, and the data is mixed up. A struct keeps the fields of one record together as a single value.

c
#include <stdio.h>

struct Student {
    char name[30];
    int roll;
    float marks;
};                                     /* note the semicolon */

int main(void) {
    struct Student s1 = {"Asha", 7, 91.5f};
    struct Student s2 = { .roll = 12, .name = "Ravi", .marks = 78.0f };   /* designated (C99) */
    s2.marks += 2.5f;                  /* the dot operator */
    printf("%s (%d): %.1f\n", s2.name, s2.roll, s2.marks);   /* Ravi (12): 80.5 */
    return 0;
}

typedef

c
typedef struct {
    char sku[16];
    int qty;
    long price_paise;
} Product;                  /* now "Product" is the type name */

Product p = { .sku = "TEA-250", .qty = 40, .price_paise = 12500 };
Without typedef you must write struct Student every time. Both styles are common; the Linux kernel prefers plain struct names.

Arrays of structs

c
Product stock[] = {
    {"TEA-250", 40, 12500},
    {"SUGAR-1K", 25, 4800},
    {"MILK-500", 0, 2900},
};
size_t n = sizeof stock / sizeof stock[0];
for (size_t i = 0; i < n; i++) {
    if (stock[i].qty == 0) printf("Restock %s\n", stock[i].sku);   /* Restock MILK-500 */
}

Copying, passing and returning

Unlike arrays, structs can be assigned with = (all members are copied, including arrays inside), passed to functions by value (the function gets a copy) and returned from functions. For big structs, passing a pointer (next topic) avoids copying many bytes. Structs cannot be compared with ==; compare the members you care about.

c
Product restocked(Product p, int extra) {   /* receives a copy */
    p.qty += extra;
    return p;                               /* returns a copy */
}
Product a = stock[2];
Product b = restocked(a, 100);              /* a.qty is still 0; b.qty is 100 */
Careful: Comparing structs with == does not compile, and memcmp on structs is unreliable because of padding bytes (topic 3) that may contain garbage. Write a function such as int product_equal(const Product *a, const Product *b) that compares the meaningful fields.
Think of it like this: A struct is like a filled-in admission form: one sheet with labelled boxes (name, roll number, marks) that travels together. An array of structs is a file of such forms; sorting the file moves whole forms, never mixing one student's name with another's marks.
Tip: Group fields that belong to one real-world thing into a struct even in small programs. It makes functions shorter: print_student(&s) instead of print_student(name, roll, marks, city, phone).

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Structs · 1/6

Structs

In this lesson you will group related data into structs.

Prefer a video by a teacher? Find free videos on “c structures struct typedef designated initializer tutorial” on YouTube ↗

In real life: A train ticket record

A ticket-printing program for a small railway counter keeps each ticket as a struct with the PNR, train number, passenger name, class and fare, so tickets can be stored in arrays, sorted and printed as single units.

c
typedef struct {
    char pnr[11];
    int train_no;
    char passenger[40];
    char travel_class[4];   /* "SL", "3A", "2A" … */
    long fare_paise;
} Ticket;

Ticket t = { .pnr = "4521367890", .train_no = 12951, .passenger = "Meena Iyer",
             .travel_class = "3A", .fare_paise = 215500 };
printf("%s | %d | %s | %s | Rs %.2f\n", t.pnr, t.train_no, t.passenger, t.travel_class, t.fare_paise / 100.0);

Practice (0/3 done)

Task 1 · Question

What does this print? typedef struct { int x, y; } Point; Point a = {1, 2}; Point b = a; b.x = 9; printf("%d %d\n", a.x, b.x);

Task 2 · Question

Which line does NOT compile? 1: struct S { int a; } s1 = {1}, s2 = {1}; 2: s2 = s1; 3: if (s1 == s2) puts("same"); 4: printf("%d", s1.a);

Task 3 · Practice

Define typedef struct { char name[30]; int roll; int marks[3]; } Student. Create an array of 4 students with designated initialisers, write int total(Student s) and void print_student(Student s), and print each student with their total. Then find and print the topper.

Quick quiz

Question 1

1.Which operator accesses a member of a struct variable?

Question 2

2.What does typedef do?

Question 3

3.Can you assign one struct to another of the same type with =?

Question 4

4.When passed to a function by value, a struct…

Read more (free)

Before this, learn

This topic builds on these. If something here feels new, open them first.

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which operator accesses a member of a struct variable?

Answer: .

-> is for pointers to structs.

What does typedef do?

Answer: Creates another name for a type

It is an alias.

Can you assign one struct to another of the same type with =?

Answer: Yes, all members are copied

Struct assignment copies everything.

When passed to a function by value, a struct…

Answer: Is copied

Pass a pointer to avoid the copy.

Can a struct contain a member of its own struct type (not a pointer)?Related

Answer: No: it would be infinitely large; it can contain a pointer to its type

Self-reference must be through a pointer.

From Pointers to structs and the arrow operator

What does assigning one struct variable to another do?Related

Answer: Copies all the fields

Structs are values; assignment copies every field.

From Structs and methods

After let b = Student { roll: 2, ..a }; where a has String fields, what is true?Related

Answer: a's String fields were moved into b

Struct update syntax moves non-Copy fields.

From Structs: your own data types

What is the only difference between struct and class in C++?Related

Answer: Default member access: public for struct, private for class

Everything else, including functions and inheritance, works the same.

From Classes and objects: data plus behaviour

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 4 more topics in “Structs, unions, enums and files” before its exam: Pointers to structs and the arrow operator, Unions, enums and memory layout, Reading and writing text files, Binary files and records.
  2. Module 7 exam: Structs, unions, enums and files · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, The preprocessor, multi-file programs and make. 60 topics left in the course before the final exam.

← Previous: Dynamic strings and 2D arrays