【指针与结构体的使用详解】
指针与结构体的使用详解(C语言)
在C语言中,结构体(struct) 和 指针(pointer) 是两个非常重要的概念。将它们结合使用,可以实现很多复杂的数据结构,比如链表、树、图等。
一、结构体基本使用
1. 定义结构体
struct Person {char name[50];int age;float height;
};
这定义了一个名为 Person
的结构体类型,包含三个成员:名字、年龄、身高。
2. 声明结构体变量
struct Person p1;
也可以用 typedef
简化:
typedef struct {char name[50];int age;float height;
} Person;Person p2; // 直接使用 Person 类型
二、指针与结构体的结合使用
1. 定义结构体指针
struct Person *ptr;
或使用 typedef
后的简写:
Person *ptr;
2. 给结构体指针分配内存
ptr = (Person*)malloc(sizeof(Person));
注意:使用完后记得释放内存:
free(ptr);
3. 访问结构体成员(两种方式)
- 点运算符(.):用于普通结构体变量
- 箭头运算符(->):用于结构体指针
Person p;
p.age = 20;Person* ptr = &p;
ptr->age = 25; // 等价于 (*ptr).age = 25;
三、指针与结构体在链表中的典型应用
链表是最经典的结构体与指针结合使用的例子。
1. 定义链表结构体
typedef struct Node {int data;struct Node* next; // 指向下一个节点
} Node, *LinkList;
Node
表示链表节点;LinkList
是指向Node
的指针,常用于表示链表头指针。
2. 创建链表节点
Node* createNode(int value) {Node* newNode = (Node*)malloc(sizeof(Node));if (!newNode) {printf("内存分配失败\n");exit(1);}newNode->data = value;newNode->next = NULL;return newNode;
}
3. 尾插法创建链表
LinkList createList() {int value;LinkList head = NULL, tail = NULL;printf("请输入整数序列(输入9999结束):\n");while (1) {scanf("%d", &value);if (value == 9999) break;Node* newNode = createNode(value);if (head == NULL) {head = tail = newNode;} else {tail->next = newNode;tail = newNode;}}return head;
}
4. 打印链表
void printList(LinkList head) {Node* current = head;while (current != NULL) {printf("%d -> ", current->data);current = current->next;}printf("NULL\n");
}
5. 主函数调用
int main() {LinkList list = createList();printList(list);// 释放内存(可选)Node* current = list;while (current != NULL) {Node* temp = current;current = current->next;free(temp);}return 0;
}
四、你可能遇到的问题与解答
❓1. typedef struct Node { ... } Node, *LinkList;
是什么意思?
Node
是结构体类型别名,等价于struct Node
;LinkList
是指向Node
的指针别名,等价于Node*
;- 常用于链表定义,简化写法。
✅ 示例:
LinkList head; // 等价于 Node* head;
❓2. 为什么用指针访问结构体成员要用 ->
而不是 .
?
.
用于普通结构体变量;->
是(*ptr).
的简写方式,用于结构体指针。
✅ 示例:
Node node;
node.data = 10; // 正确Node* ptr = &node;
ptr->data = 20; // 正确
(*ptr).data = 30; // 也正确,但写法麻烦
❓3. malloc
是做什么的?为什么结构体要动态分配?
malloc
是在堆上分配内存;- 结构体变量如果在函数中定义,函数结束后就会被释放;
- 使用
malloc
可以在函数外部继续访问结构体内容。
✅ 示例:
Node* createNode(int value) {Node* node = (Node*)malloc(sizeof(Node));node->data = value;node->next = NULL;return node;
}
❓4. 为什么要用 typedef
?
- 简化结构体声明;
- 避免每次都写
struct Node
; - 提高代码可读性和可维护性。
✅ 不使用 typedef:
struct Node {int data;struct Node* next;
};
struct Node* head;
✅ 使用 typedef:
typedef struct Node {int data;struct Node* next;
} Node;Node* head;
❓5. Node* head = NULL;
和 LinkList head = NULL;
是一样的吗?
✅ 是的,它们是等价的。
Node* head
和LinkList head
都是结构体指针;LinkList
是Node*
的别名。
五、完整示例代码
#include <stdio.h>
#include <stdlib.h>// 定义链表结构体
typedef struct Node {int data;struct Node* next;
} Node, *LinkList;// 创建节点
Node* createNode(int value) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = value;newNode->next = NULL;return newNode;
}// 创建链表(尾插法)
LinkList createList() {int value;LinkList head = NULL, tail = NULL;printf("请输入整数序列(输入9999结束):\n");while (1) {scanf("%d", &value);if (value == 9999) break;Node* newNode = createNode(value);if (head == NULL) {head = tail = newNode;} else {tail->next = newNode;tail = newNode;}}return head;
}// 打印链表
void printList(LinkList head) {Node* current = head;while (current != NULL) {printf("%d -> ", current->data);current = current->next;}printf("NULL\n");
}// 主函数
int main() {LinkList list = createList();printList(list);// 释放内存Node* current = list;while (current != NULL) {Node* temp = current;current = current->next;free(temp);}return 0;
}
六、总结
概念 | 说明 |
---|---|
struct | 定义结构体类型,封装多个不同类型的变量 |
typedef | 给结构体类型取别名,简化代码 |
-> | 用指针访问结构体成员时使用 |
malloc | 动态分配内存,用于创建结构体节点 |
Node* / LinkList | 都是结构体指针,用于链表操作 |
✅ 你可能需要练习的场景
- 创建双向链表(含
prev
和next
指针) - 使用结构体模拟学生管理系统
- 用结构体和指针实现栈、队列