2. 结构体指针

这节课我们来学习指向结构体的指针。

前面学过指针。指针的值实际就是一段内存地址的起始地址。指针的类型是使用指针的关键,它决定了编译器对指针解引用后的地址中的数据如何操作。

结构体指针 就是指向结构体的指针。我们可以通过结构体指针来将一段内存看成是一个结构体。然后对其进行操作。

结构体指针同样是 C 语言中非常常用且重要的使用场景。

结构体指针的定义语法

struct 结构体名 *结构体指针名1, *结构体指针名2, ...;

从上面的语法可以看出,结构体指针的定义语法和其它指针的定义语法没有区别。

示例

定义一个指针 pstr 分别指向 zhang3 和 li4 连个结构体类型的变量,然后使用指针访问其结构体内部的成员。

// filename: struct_pointer.c
#include <stdio.h>

struct student {
    char name[32];  // 姓名
    int age;  // 年龄
    float height; // 身高
};

int main(int argc, char * argv[]) {
    struct student zhang3 = {"zhang san", 18, 1.73};
    struct student li4 = {.age = 19, .height = 1.80, .name = "li si"};
    struct student * pstu = NULL;

    pstu = &zhang3;  // 将指针指向结构体变量 zhang3
    printf("姓名:%s,年龄:%d,身高:%.2f\n",(*pstu).name,(*pstu).age,(*pstu).height);

    pstu = &li4;  // 将指针指向结构体变量 li4
    printf("姓名:%s,年龄:%d,身高:%.2f\n",(*pstu).name,(*pstu).age,(*pstu).height);

    return 0;
}

运行结果如下

weimingze@mzstudio:~$ gcc -o struct_pointer struct_pointer.c
weimingze@mzstudio:~$ ./struct_pointer
姓名:zhang san,年龄:18,身高:1.73
姓名:li si,年龄:19,身高:1.80

可见我们使用指针 pstu 依旧可以访问结构体 zhang3li4 内的成员变量。

上述示例中我们要先将指针解引用 *pstr 然后再使用成员访问运算符 . 来访问内部的成员。在上述示例中我们使用的 *pstu 解引用时要将解引用后加一个括号然后再用 . 运算符,这是因为 成员访问运算符 . 的优先级比指针解引用运算符 * 的优先级高。因此我们在使用结构体指针访问结构体成员变量时需要写成 (*pstu).name 而不是 *pstu.name 就是这个原因。

指针成员访问运算符 ->

基于上述结构体指针访问结构体成员变量的应用场景,C 语言提供了指针成员访问运算符 -> 来将指针解引用 * 后再用 成员访问运算符 . 的两步运算整合成一个运算符的 指针成员访问运算符 ->

语法如下:

结构体指针->结构体成员变量名

即上述示例代码

printf("姓名:%s,年龄:%d,身高:%.2f\n",(*pstu).name,(*pstu).age,(*pstu).height);

可以改写成

printf("姓名:%s,年龄:%d,身高:%.2f\n",pstu->name,pstu->age,pstu->height);

效果完全一样。

改写后的示例如下:

// filename: struct_pointer.c
#include <stdio.h>

struct student {
    char name[32];  // 姓名
    int age;  // 年龄
    float height; // 身高
};

int main(int argc, char * argv[]) {
    struct student zhang3 = {"zhang san", 18, 1.73};
    struct student li4 = {.age = 19, .height = 1.80, .name = "li si"};
    struct student * pstu = NULL;

    pstu = &zhang3;  // 将指针指向结构体变量 zhang3
    printf("姓名:%s,年龄:%d,身高:%.2f\n", pstu->name, pstu->age, pstu->height);

    pstu = &li4;  // 将指针指向结构体变量 li4
    printf("姓名:%s,年龄:%d,身高:%.2f\n", pstu->name, pstu->age, pstu->height);

    return 0;
}

其运行结果与上述示例完全相同。

实验

  1. 改写上述示例程序,尝试使用指针对结构体进行访问。