1. 引言
在 C/C++ 编程中,结构体(struct
)和指针(pointer
)是常用的数据结构。访问结构体成员时,我们会用到 .
(点运算符) 和 ->
(箭头运算符),但许多初学者容易混淆它们的用法。本文将详细解析它们的区别,并通过代码示例帮助读者彻底掌握。
2. 基本概念
(1).
(点运算符)
-
适用对象:结构体变量(或对象)本身(非指针)。
-
作用:直接访问结构体的成员。
-
示例:
struct Student { char name[20]; int age; }; struct Student stu; // stu 是结构体变量 stu.age = 18; // 使用 . 访问成员
(2)->
(箭头运算符)
-
适用对象:指向结构体的指针。
-
作用:等价于
(*ptr).
,即先解引用指针,再访问成员。 -
示例:
struct Student *pStu = &stu; // pStu 是指向结构体的指针 pStu->age = 20; // 使用 -> 访问成员
等价于:
(*pStu).age = 20; // 先解引用,再用 . 访问
3. 关键区别总结
运算符 | 适用对象 | 等效形式 | 示例 |
---|---|---|---|
q. | 结构体变量(非指针) | 无 | stu.age = 18; |
q-> | 结构体指针 | (*q). | pStu->age = 20; |
记忆口诀:
“点号跟对象,箭头跟指针”
或
“有箭头(->)的地方一定是指针”
4. 常见错误分析
错误 1:对指针使用 .
struct Student *pStu = malloc(sizeof(struct Student));
pStu.age = 18; // 错误!pStu 是指针,应该用 ->
修正:
pStu->age = 18; // 正确
错误 2:对非指针使用 ->
struct Student stu;
stu->age = 18; // 错误!stu 不是指针,应该用 .
修正:
stu.age = 18; // 正确
5. 实际代码示例
示例 1:链表节点的访问
typedef struct Node {
int data;
struct Node *next;
} Node;
int main() {
Node n1 = {10, NULL}; // 结构体变量
Node *pNode = &n1; // 结构体指针
// 正确访问方式
n1.data = 20; // 使用 .
pNode->data = 30; // 使用 ->
(*pNode).data = 40; // 等价于 pNode->data
return 0;
}
示例 2:队列的实现(结合 struct
和指针)
typedef struct {
int front, rear;
int data[100];
} Queue;
void initQueue(Queue *q) {
q->front = q->rear = 0; // q 是指针,必须用 ->
}
int main() {
Queue q; // q 是结构体变量
initQueue(&q); // 传指针
q.front = 1; // q 是变量,用 .
return 0;
}
6. 为什么 C/C++ 要区分 .
和 ->
?
-
语法清晰性:通过不同的运算符区分“直接访问”和“指针访问”,使代码更易读。
-
编译器优化:明确运算符类型可以帮助编译器生成更高效的代码。
-
避免错误:强制区分可以减少因误用指针和变量导致的 bug。
7. 总结
-
.
:用于直接访问 结构体变量(非指针) 的成员。 -
->
:用于访问 结构体指针 的成员(等价于(*ptr).
)。 -
常见错误:
-
对指针使用
.
→ 编译错误。 -
对非指针使用
->
→ 编译错误。
-
-
记忆技巧:
-
“点号跟对象,箭头跟指针”
-
“
->
左边必须是指针”
-
掌握这一区别后,可以更准确地操作结构体和指针,避免低级错误!