当前位置: 首页 > news >正文

【指针与结构体的使用详解】

指针与结构体的使用详解(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* headLinkList head 都是结构体指针;
  • LinkListNode* 的别名。

五、完整示例代码

#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都是结构体指针,用于链表操作

✅ 你可能需要练习的场景

  • 创建双向链表(含 prevnext 指针)
  • 使用结构体模拟学生管理系统
  • 用结构体和指针实现栈、队列
http://www.dtcms.com/a/262764.html

相关文章:

  • nis打包(HM NIS EDIT脚本编辑器)
  • 多路转接 poll
  • UV包管理学习 - 解决Python包线上线下版本不一致的问题
  • C/C++ 使用rapidjson库 操作Json格式文件(创建、插入、解析、修改、删除)
  • 【AI时代速通QT】第四节:Windows下Qt Creator调试指南
  • 百胜软件获邀走进华为,AI实践经验分享精彩绽放
  • 设计模式之外观模式
  • Hadoop WordCount 程序实现与执行指南
  • MidJourney生成东汉末年项羽全身像提示词
  • 多线程环境下的线程安全资源与缓存池设计:ThreadSafeObject 与 CachePool 实例解析
  • 深入理解 MVCC:数据库高并发的核心引擎
  • LabVIEW键盘鼠标监测控制
  • 七天学会SpringCloud分布式微服务——06——Sentinel
  • 【软考中级·软件评测师】下午题·面向对象测试之架构考点全析:分层、分布式、微内核与事件驱动
  • 通过python+openCV实现对图片中箭头方向的判断
  • LeetCode 594. 最长和谐子序列
  • 关于 java:8. Java 内存模型与 JVM 基础
  • 汇编基础介绍——ARMv8指令集(四)
  • 【c/c++1】数据类型/指针/结构体,static/extern/makefile/文件
  • 【c/c++3】类和对象,vector容器,类继承和多态,systemd,stdboost
  • Ragflow本地部署和基于知识库的智能问答测试
  • 机器学习在智能电网中的应用:负荷预测与能源管理
  • 【鸿蒙中级】
  • 面试复盘6.0
  • 「Java案例」输出24个希腊字母
  • 深入理解 Dubbo 负载均衡:原理、源码与实践
  • Redis Cluster Gossip 协议
  • 指针篇(6)- sizeof和strlen,数组和指针笔试题
  • 免费SSL证书一键申请与自动续期
  • MySQL-复合查询