C Language Structure Pointer: Pointer + Structure = A Powerful Combination

Scan the code to follow Chip Dynamics and say goodbye to “chip” blockage!

C Language Structure Pointer: Pointer + Structure = A Powerful CombinationC Language Structure Pointer: Pointer + Structure = A Powerful CombinationSearch WeChatC Language Structure Pointer: Pointer + Structure = A Powerful CombinationChip DynamicsC Language Structure Pointer: Pointer + Structure = A Powerful Combination

You might ask: “Isn’t the structure variable itself capable of storing data? Why bother using a pointer?”

For example: Suppose you have a variable of type struct Student named stu1 (equivalent to a “student file bag”), which contains name, age, and score. If you directly manipulate stu1, you have to “carry” the entire variable name every time you modify a member (for example, strcpy(stu1.name, “Zhang San”);). But if you have a pointer p_stu that stores the memory address of stu1 (for example, 0x7ffe5a3b2c10), you only need to use p_stu->name = “Zhang San”; to directly “poke” the data location—like giving the data a “shortcut entrance”!

More importantly: When you need to pass a bunch of structure data to a function, passing the variable will copy the entire “file bag” (which could be dozens or hundreds of bytes), while passing the pointer only requires copying one address (4 or 8 bytes)—efficiency skyrockets!

Pointer to Structure Variable

Suppose you have a variable of type struct Student named stu1 (equivalent to a “student file bag”), which contains name, age, and score. The pointer p_stu pointing to it is the “delivery address” of this file bag—telling you “where the data is stored in memory”.

Code Example:

#include <stdio.h>#include <string.h>// Define student structure templatestruct Student {    char name[20];    int age;    float score;};int main() {    struct Student stu1;       // A student file bag (variable)    struct Student* p_stu;     // A pointer to the student file bag (address label)    // Label the pointer: make it point to the address of stu1    p_stu = &stu1;  // & is the address operator, p_stu now points to the memory location of stu1    // Modify the contents of the file bag through the pointer (using the -> operator)    strcpy(p_stu->name, "Zhang San");  // Equivalent to strcpy(stu1.name, "Zhang San");    p_stu->age = 18;              // Equivalent to stu1.age = 18;    p_stu->score = 90.5;          // Equivalent to stu1.score = 90.5;    // Print results (two ways to verify)    printf("Accessing through original variable: %s, %d years old, %.1f points", stu1.name, stu1.age, stu1.score);    printf("Accessing through pointer: %s, %d years old, %.1f points", p_stu->name, p_stu->age, p_stu->score);    return 0;}

Output Result:

Accessing through original variable: Zhang San, 18 years old, 90.5 points  Accessing through pointer: Zhang San, 18 years old, 90.5 points 

Key Concept Analysis:

  • The essence of pointers: p_stu is a variable that stores the memory address of stu1 (for example, 0x7ffe5a3b2c10).

  • The -> operator: specifically used to access structure members through pointers (equivalent to (*p_stu).member name, but -> is more concise).

  • Pointer “validity”: a pointer must point to a variable with allocated memory (like &stu1), otherwise it is a “wild pointer” (which can cause the program to crash).

Pointer to Structure Array

If you have a structure array class[5] (equivalent to a “file bag warehouse” that can store 5 students), the pointer p_class pointing to it is the “blueprint” of this warehouse—telling you “where the entrance of the warehouse is” and allowing you to quickly locate any file bag by moving the pointer.

Code Example:

#include <stdio.h>#include <string.h>struct Student {    char name[20];    int age;    float score;};int main() {    struct Student class[3] = {  // A warehouse that stores 3 students (array)        {"Zhang San", 18, 90.5},        {"Li Si", 19, 85.0},        {"Wang Wu", 20, 92.5}    };    struct Student* p_class;  // Pointer to the warehouse (blueprint)    // Make the pointer point to the entrance of the warehouse (the first file bag class[0])    p_class = class;  // The array name class is the address of the first element, equivalent to &p_class[0]    // Access array elements through the pointer (the pointer's step size is the size of the structure)    printf("First student: %s, %d years old", p_class->name, p_class->age);  // class[0]    p_class++;  // Move the pointer to the next file bag (class[1], step size = sizeof(struct Student))    printf("Second student: %s, %d years old", p_class->name, p_class->age);  // class[1]    p_class += 2;  // Move the pointer 2 steps (to class[3], but the array only has 3 elements, out of bounds!)    printf("Third student: %s, %d years old", p_class->name, p_class->age);  // Dangerous! Out of bounds access    return 0;}

Output Result (assuming the size of the structure is 28 bytes):

First student: Zhang San, 18 years old  Second student: Li Si, 19 years old  Third student: (garbage) 

Key Concept Analysis:

  • Pointer movement step size: p_class++ will move the pointer sizeof(struct Student) bytes (for example, 28 bytes), not 1 byte (a normal int pointer moves 4 bytes). This is because each element of the structure array is a complete structure variable, and the memory is stored continuously.

  • The relationship between array names and pointers: the array name class is the address of the first element (&class[0]), so it can be directly assigned to the pointer to the structure array.

Using Structure Variables and Pointers as Function Parameters3.1 Passing Structure Variables: Copying the Entire “File Bag”

If a function needs to modify the members of a structure variable, what happens if you pass the structure variable directly?

Code Example:

void update_score(struct Student s) {  // Pass by value (copy the entire structure)    s.score = 100.0;  // Modifying the copy, the original variable remains unchanged!}int main() {    struct Student stu1 = {"Zhang San", 18, 90.5};    update_score(stu1);     printf("Score: %f", stu1.score);  // Outputs 90.5 (not changed!)    return 0;}

Consequence: The function modifies a copy of the structure (which is unrelated to the original variable), and the original variable will not be modified.

Principle: In C language, function parameters are “passed by value”—when passing a structure variable, the entire content of the structure is copied to the local variable inside the function, and modifying the local variable does not affect the original variable.

3.2 Passing Structure Pointers: Directly Manipulating the “File Bag”

If you want the function to modify the original structure variable, you should pass its pointer!

Code Example:

void update_score(struct Student* p_s) {  // Pass pointer (address)    p_s->score = 100.0;  // Directly modify the member of the original variable}int main() {    struct Student stu1 = {"Zhang San", 18, 90.5};    update_score(&stu1);  // Pass the address of stu1    printf("Score: %f", stu1.score);  // Outputs 100.0 (successfully modified!)    return 0;}

Advantages:

  • High efficiency: pointers only occupy 4/8 bytes (32/64-bit systems), which is much faster than copying the entire structure (which could be dozens or hundreds of bytes).

  • Powerful functionality: can modify all members of the original variable through pointers.

3.3 Three Major Pitfalls of Function Parameters

Pitfall 1: Passing a pointer without checking for null value

Error Code:

void print_info(struct Student* p) {    printf("%s", p->name);  // If p is NULL, it crashes!}int main(){    print_info(NULL);  // Pass null pointer    return 0;}

Consequence: p->name attempts to access memory pointed to by the null pointer (address 0), causing the program to crash.

Solution: Check if the pointer is null inside the function:

void print_info(struct Student* p) {    if (p == NULL) {  // Defensive check        printf("Pointer is null!");        return;    }    printf("%s", p->name);}

Pitfall 2: Passing a pointer but modifying the pointer itself (not the data it points to)

Error Code:

void alloc_memory(struct Student* p) {    p = (struct Student*)malloc(sizeof(struct Student));  // Modifying the local pointer p, the original pointer remains unchanged!}int main() {    struct Student* p_stu = NULL;    alloc_memory(p_stu);  // Pass the value of p_stu (NULL)    printf("%p", p_stu);  // Outputs 0x0 (allocation failed!)    return 0;}

Consequence: The function modifies the local pointer p (a copy of the original pointer), and the original pointer p_stu remains NULL.

Solution: If you need to modify the original pointer’s direction (for example, dynamic memory allocation), you need to pass a pointer to the pointer (double pointer):

void alloc_memory(struct Student** pp) {  // Pass double pointer (pointer to pointer)    *pp = (struct Student*)malloc(sizeof(struct Student));  // Modify the original pointer p_stu's direction}int main() {    struct Student* p_stu = NULL;    alloc_memory(&p_stu);  // Pass the address of p_stu (double pointer)    printf("%p", p_stu);  // Outputs valid address (allocation successful!)    free(p_stu);    return 0;}

Pitfall 3: Returning a pointer to a local variable from a function

Error Code:

struct Student* create_student() {    struct Student s;  // Local variable (exists on the stack)    strcpy(s.name, "Zhang San");    return &s  // Returning the address of a local variable (dangerous!)}int main() {    struct Student* p = create_student();    printf("%s", p->name);  // Crashes! s has been destroyed, p is a dangling pointer    return 0;}

Consequence: The local variable s is destroyed after the function ends, and the pointer p points to invalid memory, causing a crash when accessed.

Solution: Return dynamically allocated memory (variables on the heap are not automatically destroyed):

struct Student* create_student() {    struct Student* p = (struct Student*)malloc(sizeof(struct Student));  // Heap memory    strcpy(p->name, "Zhang San");    return p;  // Safe: heap memory is manually released}int main() {    struct Student* p = create_student();    printf("%s", p->name);  // Outputs Zhang San    free(p);  // Manually release    return 0;}

C Language Structure Pointer: Pointer + Structure = A Powerful Combination

If you find the article useful, click Like“, Share“, Recommend“!

Leave a Comment