首页 > 编程笔记 > C语言笔记(精华版)

C语言结构体指针的定义和使用(附带示例)

在C语言中,结构体指针是一种特殊类型的指针,它指向一个结构体变量的内存地址。换句话说,结构体指针的本质是一个指针变量,它存储的是一个结构体变量的内存地址。
 

通过结构体指针,我们可以间接地访问和修改结构体中的成员;这种间接访问方式在某些情况下比直接使用结构体变量更加高效,特别是在传递大型结构体数据时。


结构体指针的语法格式如下:

struct 结构体名 *指针变量名;

在这个语法格式中,struct关键字表明我们正在定义一个结构体类型的指针,结构体名是之前定义的结构体的名称,星号*表示这是一个指针。


让我们通过一个具体的例子来理解结构体指针的定义和使用。假设我们有一个表示学生信息的结构体:

struct Student {
    int id;
    char name[50];
    float score;
};

现在,我们可以定义一个指向 Student 结构体的指针:

struct Student *pStudent;

这里,pStudent 是一个指针,它可以存储 Student 类型结构体变量的地址。接下来,我们可以创建一个 Student 结构体变量,并让 pStudent 指向它:

struct Student s1 = {1001, "张三", 85.5};
pStudent = &s1;

现在,pStudent 指向了 s1 结构体变量的内存地址,我们可以通过这个指针来访问结构体的成员。
 

在C语言中,有两种方式可以通过结构体指针访问成员:
 

1) 使用箭头运算符->

printf("学号:%d\n", pStudent->id);
printf("姓名:%s\n", pStudent->name);
printf("分数:%.1f\n", pStudent->score);


2) 使用间接引用运算符*和点运算符.

printf("学号:%d\n", (*pStudent).id);
printf("姓名:%s\n", (*pStudent).name);
printf("分数:%.1f\n", (*pStudent).score);

这两种方式在功能上是等价的,但箭头运算符->更常用,因为它更简洁。


结构体指针的一个重要应用是在函数参数传递中。当我们需要在函数中修改结构体的内容时,传递结构体指针比传递结构体本身更有效率。这是因为传递指针只需要复制一个地址值,而传递整个结构体则需要复制结构体的所有数据。例如:

void updateScore(struct Student *s, float newScore) {
    s->score = newScore;
}

int main() {
    struct Student s1 = {1001, "张三", 85.5};
    updateScore(&s1, 90.0);
    printf("更新后的分数:%.1f\n", s1.score);
    return 0;
}

在这个例子中,updateScore 函数接收一个 Student 结构体的指针和一个新的分数值。通过指针,函数可以直接修改原始结构体中的 score 成员。


结构体指针还可以用于动态内存分配,我们可以使用 malloc 函数在堆上分配内存来创建结构体:

struct Student *pStudent = (struct Student *)malloc(sizeof(struct Student));
if (pStudent != NULL) {
    pStudent->id = 1002;
    strcpy(pStudent->name, "李四");
    pStudent->score = 78.5;
    
    // 使用完毕后记得释放内存
    free(pStudent);
}

这种方法允许我们在运行时动态创建结构体,这在处理大量数据或者数据量不确定的情况下特别有用。
 

文章最后,让我们通过一个完整的例子来展示结构体指针的定义和使用:

#include <stdio.h>
#include <stdlib.h>

// 定义一个表示学生的结构体
struct Student {
    char name[50];
    int age;
    float gpa;
};

// 函数原型
void printStudent(struct Student *s);
void updateGPA(struct Student *s, float newGPA);

int main() {
    // 创建一个 Student 结构体变量
    struct Student alice = {"Alice", 20, 3.5};
    
    // 创建一个指向 alice 的结构体指针
    struct Student *pStudent = &alice;
    
    // 使用结构体指针打印学生信息
    printf("初始学生信息:\n");
    printStudent(pStudent);
    
    // 使用结构体指针更新 GPA
    updateGPA(pStudent, 3.8);
    
    // 再次打印更新后的学生信息
    printf("\n更新后的学生信息:\n");
    printStudent(pStudent);
    
    return 0;
}

// 使用结构体指针打印学生信息的函数
void printStudent(struct Student *s) {
    printf("姓名: %s\n", s->name);
    printf("年龄: %d\n", s->age);
    printf("GPA: %.2f\n", s->gpa);
}

// 使用结构体指针更新学生 GPA 的函数
void updateGPA(struct Student *s, float newGPA) {
    s->gpa = newGPA;
}

这个程序的输出结果如下:

初始学生信息:
姓名: Alice
年龄: 20
GPA: 3.50

更新后的学生信息:
姓名: Alice
年龄: 20
GPA: 3.80

在这个例子中,我们定义了一个 Student 结构体,然后创建了一个指向 Student 结构体的指针,我们使用这个指针来访问和修改结构体的成员。注意我们如何使用箭头运算符 -> 来通过指针访问结构体成员。
 

printStudent 和 updateGPA 这两个函数都接受一个 Student 结构体指针作为参数,这种方式比传递整个结构体更高效,因为它只传递了一个内存地址,而不是复制整个结构体。

相关文章