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 依旧可以访问结构体 zhang3 和 li4 内的成员变量。
上述示例中我们要先将指针解引用 *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;
}
其运行结果与上述示例完全相同。
实验
- 改写上述示例程序,尝试使用指针对结构体进行访问。