数据结构——指针

指针是 C/C++ 语言中最核心也最具特色的概念,可以把它理解为 C 语言的"灵魂"。掌握指针,是深入理解内存、数据结构等高级主题的关键。

🤔 什么是指针?

简单来说,指针就是内存地址。

我们可以用一个生活中的例子来类比:

  • 内存 就像一栋巨大的宿舍楼。
  • 内存单元(字节) 就是楼里的每一个房间。
  • 地址 就是每个房间唯一的门牌号。
  • 变量 就是住在某个房间里的"人"或"物品"。
  • 指针 就是一个小本子,上面记录着某个变量所住房间的"门牌号"。

所以,指针变量就是一种特殊的变量,它不直接存储数据,而是专门用来存储另一个变量的内存地址。

🔑 两个核心符号:& 和 *

理解指针,必须掌握两个操作符:

  1. 取地址符 &

    • 作用:获取一个变量在内存中的地址(门牌号)。
    • 示例 :&a 表示获取变量 a 的地址。
  2. 解引用符 *

    • 作用:通过指针中存储的地址,找到并访问该地址上存放的实际数据(根据门牌号找到房间里的人)。
    • 示例 :如果指针 p 存储了变量 a 的地址,那么 *p 就代表变量 a 本身。

特别注意 :在定义指针时,* 的作用是声明,表示"这是一个指针变量",而不是解引用。

💻 指针的基本使用

让我们通过一段代码来直观地感受一下:

c 复制代码
#include <stdio.h>

int main() {
    int a = 100;      // 定义一个整型变量 a,值为 100
    int *p = &a;      // 定义一个整型指针 p,并将 a 的地址赋给它

    printf("a 的值是: %d\n", a);     // 输出: 100
    printf("a 的地址是: %p\n", &a);  // 输出 a 的内存地址
    printf("p 的值是: %p\n", p);     // 输出 p 中存储的地址,和 &a 相同
    printf("*p 的值是: %d\n", *p);   // 输出: 100,通过地址访问 a 的值

    // 通过指针修改 a 的值
    *p = 200;
    printf("修改后,a 的值是: %d\n", a); // 输出: 200

    return 0;
}

这段代码清晰地展示了如何通过指针 p 来间接访问和修改变量 a 的值。

❓ 为什么指针要有类型?

你可能会问,既然指针存的都是地址(一个数字),为什么还要分 int*、char*、double* 呢?

这是因为指针的类型决定了它的两种关键行为:

  1. 解引用时,操作多少字节

    • char* 解引用时,只访问 1个字节 的数据。
    • int* 解引用时,会访问 4个字节 的数据(在大多数系统上)。
    • 这决定了指针如何"解释"它指向的内存内容。
  2. 指针运算时,移动的步长

    • 当你执行 p + 1 时,指针 p 并不是简单地将地址值加1。
    • char* 类型的指针加1,地址会向后移动 1个字节。
    • int* 类型的指针加1,地址会向后移动 4个字节 ,刚好跳到下一个 int 类型数据的位置。
    • 这保证了指针能正确地遍历数组等数据结构。

⚠️ 两个重要概念:空指针与野指针

在使用指针时,必须警惕两种危险情况:

  • 空指针 (NULL Pointer)

    • 这是一个被明确初始化为 NULL (或 0) 的指针,表示它不指向任何有效的内存地址。使用空指针是一种良好的编程习惯,可以避免意外访问。
  • 野指针 (Wild Pointer)

    • 这是一个指向了"未知"或"已释放"内存的指针。它通常是因为指针在定义时没有初始化,或者指向的变量生命周期结束后,指针没有被置为 NULL。访问野指针会导致程序崩溃或产生不可预测的错误,是编程中的大忌。

🤝 指针与引用 (C++)

在 C++ 中,引用(&)是指针的一种更安全、更易用的替代方案。它们的核心区别如下:

特性 指针 (Pointer) 引用 (Reference)
本质 存储地址的变量 变量的别名
空值 可以为空 (nullptr) 不能为空,必须初始化
重新绑定 可以改变指向 绑定后不可改变
安全性 较低,易出现野指针 较高,无空引用风险

简单来说,引用更像是一个变量的"绰号",一旦确定就不能更改,并且这个"绰号"必须对应一个真实存在的变量。

相关推荐
m0_639906941 小时前
Redis入门|五种数据结构、使用场景、持久化RDB&AOF
数据结构·数据库·redis
ZhengEnCi3 小时前
Agent 架构怎么选:从单 Agent 到多 Agent 编排的选型决策指南
算法·架构
秋天的怀念_David3 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Pniubi3 小时前
力扣283移动零(双指针法)
算法·leetcode·职场和发展
hhb_6184 小时前
大模型落地三重优化实战
人工智能·算法·机器学习
云和数据.ChenGuang4 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
2601_970703835 小时前
工业除湿机租赁:把一份租金合同拆开看
大数据·数据结构·算法·数据库架构·推荐算法
心中有你02145 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
ZhengEnCi6 小时前
同样的模型,为什么本地和云 API 差别那么大:量化精度、聊天模板与采样参数的三大元凶
人工智能·算法·llm
Flynn Liang7 小时前
RAG 答非所问/幻觉怎么破?Spring AI QuestionAnswerAdvisor 召回优化实战(TopK/重排/混合检索)
人工智能·算法·spring·rag·幻觉·springai