C 语 言 --- 指 针 2
- 指 针 的 关 系 运 算
- 指 针 的 运 算
- 指 针 ± 整 数
- 指 针 + 整 数
- 指 针 - 整 数
- 指 针 - 指 针
- 指 针 在 数 组 中 的 比 较
- 二 级 指 针
- 总结
💻作 者 简 介:曾 与 你 一 样 迷 茫,现 以 经 验 助 你 入 门 C 语 言
💡个 人 主 页:@笑口常开xpr 的 个 人 主 页
📚系 列 专 栏:C 启新程
✨代 码 趣 语:指 针 让 程 序 能 够 像 舞 者 一 样 在 内 存 的 舞 台 上 灵 活 跳 跃,自 由 访 问 不 同 的 数 据 区 域。
💪代 码 千 行,始 于 坚 持,每 日 敲 码,进 阶 编 程 之 路。
📦gitee 链 接:gitee
在 编 程 的 世 界 里,每 一 行 代 码 都 可 能 隐 藏 着 无 限 的 可 能 性 。你 是 否 想 过,一 个 小 小 的 程 序 究 竟 能 改 变 什 么?它 可 以 是 解 决 复 杂 问 题 的 工 具 ,也 可 以 是 实 现 梦 想 的 桥 梁。今 天,就 让 我 们 一 起 走 进 C 语 言 指 针 的 世 界,探 索 它 的 无 限 潜 力。
指 针 的 关 系 运 算
定 义
指 针 的 关 系 运 算 主 要 用 于 比 较 指 针 所 指 向 地 址 的 大 小 关 系。
关 系 运 算 符
指 针 关 系 运 算 符 和 变 量 的 关 系 运 算 符 一 样,主 要 包 含 以 下 6 种:
> 大 于< 小 于
>= 大 于 等 于
<= 小 于 等 于
== 等 于
!= 不 等 于
规 则
指 针 指 向 同 一 数 组:当 两 个 指 针 指 向 同 一 个 数 组 中 的 元 素 时,关 系 运 算 比 较 的 是 它 们 所 指 向 元 素 在 数 组 中 的 相 对 位 置。指 向 数 组 中 较 后 元 素 的 指 针 大 于 指 向 较 前 元 素 的 指 针。
指 针 指 向 不 同 对 象:对 指 向 不 同 对 象 的 指 针 进 行 关 系 运 算,结 果 通 常 是 未 定 义 的,除 非 这 两 个 对 象 是 同 一 个 数 组 中 的 元 素 或 者 是 同 一 个 结 构 体 中 的 成 员。
指 针 与 NULL 比 较:可 以 将 指 针 和 NULL(空 指 针)进 行 比 较,以 此 判 断 指 针 是 否 为 空。
下 面 展 示
代 码 示 例
。
#include <stdio.h>
int main()
{int arr[5] = { 1, 2, 3, 4, 5 };int* ptr1 = &arr[0];int* ptr2 = &arr[2];//比较两个指针的大小if (ptr1 < ptr2) {printf("ptr1指向的元素在ptr2指向的元素之前\n");}else {printf("ptr1指向的元素在ptr2指向的元素之后\n");}// 检查指针是否相等if (ptr1 == ptr2) {printf("ptr1和ptr2指向同一个元素\n");}else {printf("ptr1和ptr2指向不同的元素\n");}//检查指针是否为空if (ptr1 != NULL) {printf("ptr1不是空指针\n");}return 0;
}
指 针 的 运 算
指 针 ± 整 数
基 本 原 理
指 针 本 质 上 是 一 个 存 储 内 存 地 址 的 变 量。当 对 指 针 进 行 加 减 整 数 的 运 算 时,并 不 是 简 单 地 对 指 针 所 存 储 的 地 址 值 进 行 加 减,而 是 根 据 指 针 所 指 向 的数 据 类 型 的 大 小 来 进 行偏 移。
偏 移 量 的 计 算 公 式
偏 移 后 的 地 址 = 原 地 址 ± 整 数 * 数 据 类 型 的 大 小
指 针 + 整 数
指 针 加 整 数 表 示 指 针 向 前 移 动,指 向 内 存 中 后 续 的 元 素。
下 面 展 示
代 码 示 例
。
#include <stdio.h>
int main()
{int arr[5] = { 10, 20, 30, 40, 50 };int* ptr = arr; //指针ptr指向数组的第一个元素//输出ptr初始指向的值printf("初始时,ptr指向的值:%d\n",*ptr);//指针ptr加2ptr = ptr + 2;// 输出ptr加2后指向的值printf("ptr加2后,指向的值:%d\n", *ptr);return 0;
}
解 释 :指 针 + 整 数 指 针 向 前 移 动,指 向 内 存 中 后 续 的 元 素
数 组 在 内 存 的 存 储
数 组 元 素 在 内 存 中 是 连 续 存 储 的,并 且 内 存 地 址 是 按 递 增 顺 序 分 配 的。也 就 是 说,数 组 的 第 一 个 元 素 存 储 在 较 低 的 内 存 地 址 处, 随 着 元 素 下 标 的 增 加,后 续 元 素 依 次 存 储 在 更 高 的 内 存 地 址 处。
下 面 展 示
代 码 示 例
。
#include <stdio.h>
int main()
{int arr[5] = { 10, 20, 30, 40, 50 };int* ptr = &arr[0]; //指针ptr指向数组的第一个元素printf("指针初始指向的值: %d,地址:%p\n", *ptr, (void*)ptr);ptr++;//指针向前移动一个位置,指向数组的第二个元素printf("指针移动后指向的值: %d,地址:%p\n", *ptr, (void*)ptr);return 0;
}
指 针 从 数 组 第 一 个 元 素 移 动 到 第 二 个 元 素 是 朝 着 内 存 地 址 增 大 的 方 向 移 动,也 就 是 向 前 移 动,指 向 后 面 的 元 素。
指 针 - 整 数
指 针 减 整 数 表 示 指 针 向 后 移 动,指 向 内 存 中 前 面 的 元 素。
下 面 展 示
代 码 示 例
。
#include <stdio.h>
int main()
{int arr[5] = { 10, 20, 30, 40, 50 };int* ptr = &arr[4]; //指针ptr指向数组的第5个元素printf("指针初始指向的值: %d,地址:%p\n", *ptr, (void*)ptr);ptr--;//指针向后移动一个位置,指向数组的第4个元素printf("指针移动后指向的值: %d,地址:%p\n", *ptr, (void*)ptr);return 0;
}
注 意 事 项
指 针 越 界 问 题:在 进 行 指 针 加 减 整 数 运 算 时,要 确 保 指 针 不 会 越 界 访 问 数 组。越 界 访 问 可 能 会 导 致 未 定 义 行 为。
数 据 类 型 一 致 性:指 针 的 加 减 运 算 结 果 仍 然 是 一 个 指 针,且 该 指 针 的 类 型 与 原 指 针 类 型 相 同。
不 同 类 型 指 针 运 算 差 异:不 同 数 据 类 型 的 指 针 进 行 加 减 整 数 运 算 时,偏 移 量 是 不 同 的。
指 针 - 指 针
当 两 个 指 针 指 向 同 一 块 连 续 的 内 存 区 域 时,它 们 相 减 的 结 果 是 这 两 个 指 针 所 指 向 元 素 之 间 的 元 素 个 数。
下 面 展 示
代 码 示 例
。
#include<stdio.h>
int main()
{char ch[5] = { 0 };int arr[10] = { 0 };printf("%d\n", &arr[9] - &arr[0]);//printf("%d\n", &arr[0] - &ch[4]);//代码错误,两个指针要指向同一块空间return 0;
}
注 释 代 码 分 析
&arr[0] - &ch[4]:此 代 码 会 产 生 错 误,因 为 arr 和 ch 是 两 个 不 同 的 数 组,它 们 在 内 存 中 不 是 连 续 的 同 一 块 空 间。在 C 语 言 里,只 有 当 两 个 指 针 指 向 同 一 块 连 续 的 内 存 区 域 时,指 针 相 减 才 有 意 义。
总 结
& 运 算 符 用 于 获 取 变 量 或 数 组 元 素 的 内 存 地 址。
当 两 个 指 针 指 向 同 一 块 连 续 的 内 存 区 域 时,它 们 相 减 的 结 果 是 这 两 个 指 针 所 指 向 元 素 之 间 的 元 素 个 数。
若 两 个 指 针 指 向 不 同 的 内 存 区 域,进 行 指 针 相 减 操 作 会 产 生 未 定 义 行 为。
指 针 在 数 组 中 的 比 较
允 许 指 向 数 组 元 素 的 指 针 与 指 向 数 组 最 后 一 个 元 素 后 面 的 那 个 内 存 位 置 的 指 针 比 较,可 以 用 来 判 断 是 否 到 达 数 组 末 尾。
下 面 展 示
代 码 示 例
。
#include <stdio.h>
int main()
{int arr[5] = { 1, 2, 3, 4, 5 };int* ptr = arr;//指向数组最后一个元素后面的那个内存位置int* end = arr + 5;while (ptr < end) {printf("%d ", *ptr);ptr++;}printf("\n");return 0;
}
但 不 允 许 与 指 向 第 一 个 元 素 之 前 的 那 个 内 存 位 置 的 指 针 进 行 比 较,若 尝 试 与 指 向 第 一 个 元 素 之 前 的 内 存 位 置 的 指 针 进 行 比 较,会 导 致 未 定 义 行 为,C 语 言 标 准 并 没 有 对 这 种 行 为 进 行 定 义,不 同 的 编 译 器 和 运 行 环 境 可 能 会 产 生 不 同 的 结 果,甚 至 可 能 导 致 程 序 崩 溃。
下 面 展 示
代 码 示 例
。
#include <stdio.h>
int main()
{int arr[5] = { 1, 2, 3, 4, 5 };int* ptr = arr;//错误示例:指向第一个元素之前的那个内存位置int* before_start = arr - 1;//下面这行代码会产生未定义行为if (ptr > before_start) { printf("错误的比较\n");}return 0;
}
二 级 指 针
定 义
二 级 指 针 是 指 向 指 针 的 指 针,也 就 是 一 个 指 针 变 量,其 存 储 的 是 另 一 个 指 针 的 地 址。一 级 指 针 用 于 存 储 变 量 的 地 址,而 二 级 指 针 则 用 于 存 储 一 级 指 针 的 地 址。
定 义 形 式
数 据 类 型 **指 针 变 量 名;
这 里 的 数 据 类 型 表 明 二 级 指 针 最 终 指 向 的 数 据 类 型。
下 面 展 示
代 码 示 例
。
#include<stdio.h>
int main()
{int a = 10;int* pa = &a;//pa是一级指针变量int** ppa = &pa;//二级指针,第一颗*表示pa的类型是int *,第二颗*表示指针printf("%p\n", ppa);printf("%p\n", *ppa);printf("%d\n", **ppa);return 0;
}
ppa
含 义:ppa 是 一 个 二 级 指 针 变 量。ppa 被 定 义 为 int ** 类 型,其 作 用 是 存 储 一 级 指 针 pa 的 地 址。
存 储 内 容:ppa 存 储 的 是 pa 的 内 存 地 址。
*ppa
含 义:*ppa 是 对 二 级 指 针 ppa 进 行 一 次 解 引 用 操 作。*ppa 获 取 的 是 ppa 所 指 向 的 一 级 指 针 pa。
存 储 内 容:*ppa 实 际 上 就 是 pa,而 pa 存 储 的 是 变 量 a 的 地 址。也 就 是 说,*ppa 存 储 的 是 变 量 a 的 内 存 地 址。
**ppa
含 义:**ppa 是 对 二 级 指 针 ppa 进 行 两 次 解 引 用 操 作。先 通 过 第 一 次 解 引 用 *ppa 得 到 一 级 指 针 pa,再 对 pa 进 行 解 引 用 操 作 *pa,最终 获 取 到 pa 所 指 向 的 变 量 a。
存 储 内 容:**ppa 就 是 变 量 a 的 值。
ppa 存 储 的 是 一 级 指 针 pa 的 地 址,*ppa 存 储 的 是 变 量 a 的 地 址,**ppa 是 变 量 a 的 值。
总结
至 此,关 于 C 语 言 指 针 的 探 索 暂 告 一 段 落,但 你 的 编 程 征 程 才 刚 刚 启 航。写 代 码 是 与 机 器 深 度 对 话,过 程 中 虽 会 在 语 法、算 法 困 境 里 挣 扎,但 这 些 磨 砺 加 深 了 对 代 码 的 理 解。愿 你 合 上 电 脑 后,灵 感 不 断,在 C 语 言 的 世 界 里 持 续 深 耕,书 写 属 于 自 己 的 编 程 传 奇,下 一 次 开 启 ,定 有 全 新 的 精 彩 等 待。小 编 期 待 重 逢,盼 下 次 阅 读 见 你 们 更 大 进 步,共 赴 代 码 之 约!