Structures

A struct is like a custom form — it packages different types of information (name, age, grade) together into a single unit you can manage as a whole.

struct Definition and Declaration

Defining a Struct Type

C
struct Student {
    char name[20];
    int age;
    float score;
};

This defines a type struct Student. Note that the trailing semicolon is required.

Declaring Struct Variables

C
struct Student s1;
struct Student s2, s3;

You can also declare variables at the same time as defining the type:

C
struct Point {
    int x;
    int y;
} p1, p2;

Anonymous Struct

If you only need it once, you can omit the type name:

C
struct {
    int width;
    int height;
} box;
⚠️ Note: An anonymous struct cannot be used to declare new variables later. It's typically only used for one-off scenarios.

Struct Variable Initialization

Sequential Initialization

C
struct Student s1 = {"Zhang", 20, 89.5};

Designated Initializer (C99)

C
struct Student s2 = {.name = "Li", .score = 92.0, .age = 21};
💡 Tip: Designated initializers don't need to follow the declaration order. Unspecified members are automatically zeroed.

Partial Initialization

C
struct Student s3 = {"Wang"};

name is initialized; the remaining members are automatically set to 0.

Member Access

Dot Operator .

Access members through a struct variable:

C
struct Student s = {"Zhao", 19, 78.5};
printf("Name: %s\n", s.name);
printf("Age: %d\n", s.age);
s.score = 85.0;

Arrow Operator ->

Access members through a struct pointer:

C
struct Student s = {"Zhao", 19, 78.5};
struct Student *ps = &s;
printf("Name: %s\n", ps->name);
ps->age = 20;

ps->name is equivalent to (*ps).name. The -> operator is syntactic sugar — more concise when working with pointers.

💡 Tip: Mnemonic: use a dot for variables, use an arrow for pointers.

Example

C
#include <stdio.h>

struct Book {
    char title[50];
    char author[30];
    float price;
};

int main(void) {
    struct Book b1 = {.title = "The C Programming Language", .author = "K&R", .price = 45.0};
    struct Book *pb = &b1;

    printf("Title: %s\n", pb->title);
    printf("Author: %s\n", pb->author);
    printf("Price: %.1f\n", pb->price);

    pb->price = 55.0;
    printf("After discount: %.1f\n", b1.price);
    return 0;
}
▶ Try it Yourself
TEXT
Title: The C Programming Language
Author: K&R
Price: 45.0
After discount: 55.0

Struct Array

Place multiple structs in an array for unified management.

C
struct Student class[3] = {
    {"Zhang", 20, 89.5},
    {"Li", 21, 92.0},
    {"Wang", 19, 78.0}
};

for (int i = 0; i < 3; i++) {
    printf("%s %d %.1f\n", class[i].name, class[i].age, class[i].score);
}
TEXT
Zhang 20 89.5
Li 21 92.0
Wang 19 78.0

Traverse a struct array with a pointer:

C
struct Student *p = class;
for (int i = 0; i < 3; i++, p++) {
    printf("%s %.1f\n", p->name, p->score);
}

Struct Pointer

The most common use of struct pointers: avoid copying the entire struct when passing it between functions.

C
void print_student(struct Student *ps) {
    printf("%s, age %d, score %.1f\n", ps->name, ps->age, ps->score);
}

int main(void) {
    struct Student s = {"Zhang", 20, 89.5};
    print_student(&s);
    return 0;
}
TEXT
Zhang, age 20, score 89.5
⚠️ Note: Passing by value copies the entire struct. If the struct has many members or contains large arrays, the overhead is significant. Passing a pointer only copies one address.

Struct as Function Parameter

Pass by Value

C
void add_score(struct Student s, float bonus) {
    s.score += bonus;
}
⚠️ Note: When passing by value, modifications inside the function affect a copy — the original variable is unchanged.

Pass by Pointer

C
void add_score(struct Student *s, float bonus) {
    s->score += bonus;
}

Modifications through the pointer inside the function directly affect the original variable.

Example

C
#include <stdio.h>

struct Score {
    char name[20];
    int chinese;
    int math;
    int english;
};

int total(struct Score *s) {
    return s->chinese + s->math + s->english;
}

void boost(struct Score *s, int bonus) {
    s->chinese += bonus;
    s->math += bonus;
    s->english += bonus;
}

int main(void) {
    struct Score stu = {.name = "Zhou", .chinese = 80, .math = 75, .english = 88};
    printf("Original total: %d\n", total(&stu));
    boost(&stu, 5);
    printf("After bonus: %d\n", total(&stu));
    return 0;
}
▶ Try it Yourself
TEXT
Original total: 243
After bonus: 258

Struct Assignment and Comparison

Assignment

Structs of the same type can be directly assigned — members are copied one by one:

C
struct Student s1 = {"Zhang", 20, 89.5};
struct Student s2;
s2 = s1;

Comparison

⚠️ Note: Structs cannot be compared with == or !=. You must compare members individually:

C
int equal(struct Student *a, struct Student *b) {
    return a->age == b->age && a->score == b->score;
}

Nested Structs

A struct member can itself be another struct:

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

struct Employee {
    char name[20];
    struct Date birthday;
    float salary;
};

struct Employee e = {"Chen", {1995, 6, 15}, 8000.0};
printf("Birthday: %d-%02d-%02d\n", e.birthday.year, e.birthday.month, e.birthday.day);
TEXT
Birthday: 1995-06-15

❓ FAQ

Q What's the difference between . and ->?
A . accesses members through a struct variable; -> accesses members through a struct pointer. p->name is equivalent to (*p).name.
Q Can structs be compared with ==?
A No. C does not support == comparison for structs. You must compare members individually or use memcmp (but beware of padding bytes).
Q Should I pass a struct by value or by pointer?
A Generally pass by pointer — it's more efficient and allows modifying the original data. For read-only scenarios, add const protection: const struct Student *s.
Q Why must a struct definition end with a semicolon?
A Because variable declarations can immediately follow the closing brace. The semicolon tells the compiler the declaration list is complete — omitting it causes a syntax error.

📖 Summary

📝 Exercises

  1. Define struct Rectangle with width and height. Write functions float area(struct Rectangle *r) and float perimeter(struct Rectangle *r), then calculate and print the results in main
  2. Define struct Date and write a function int date_compare(struct Date *a, struct Date *b) that returns -1/0/1 indicating whether a is earlier than / equal to / later than b
  3. Define a student struct array (5 students), sort by score from highest to lowest, and print the results
100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏