news 2026/6/21 12:20:49

指针运算与指针数组——加减、相减与函数指针

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
指针运算与指针数组——加减、相减与函数指针

指针加减整数

指针可以加减整数,结果按元素大小缩放,不是按字节:

int arr[5] = {10, 20, 30, 40, 50}; int *p = arr; ​ p + 1 // 指向 arr[1],地址加 4 字节(sizeof(int)) p + 3 // 指向 arr[3],地址加 12 字节 p - 1 // 指向 arr[-1],越界,未定义行为

p++p--也常用:

int *p = arr; p++; // p 从 arr[0] 移到 arr[1] p--; // p 从 arr[1] 移回 arr[0]

为什么按元素缩放?

这是 C 语言的设计选择。如果p + 1是加 1 字节,那遍历数组时你得自己算p + sizeof(int)——繁琐且容易出错。按元素缩放让你可以直接p++跳到下一个元素。

指针相减

两个指向同一数组的指针可以相减,结果是元素个数

int arr[5] = {10, 20, 30, 40, 50}; int *p1 = &arr[1]; int *p2 = &arr[4]; ​ printf("%td\n", p2 - p1); // 3(间隔 3 个元素)

注意结果是元素个数(3),不是字节数(12)。

限制:只能对同一数组的指针做。不同数组的指针相减是未定义行为。

指针比较

同一数组的指针可以比较大小:

int arr[5]; int *p = &arr[1]; int *q = &arr[3]; ​ if (p < q) printf("p 在 q 前面\n"); // arr[1] 地址更小 if (p == q) printf("相同\n"); if (p != q) printf("不同\n");

同样,只对同一数组有意义。

下标的另一种写法

int arr[5] = {10, 20, 30, 40, 50}; int *p = arr; ​ // 以下全部等价 p[3] // 40 *(p + 3) // 40 3[p] // 40!合法但别这么写

3[p]为什么合法?编译器将a[b]解析为*(a + b),加法交换律,*(3 + p)*(p + 3)一样。

语法上合法,风格上禁止——写了会被同事打。

函数指针

函数也有地址,可以用指针存储:

int add(int a, int b) { return a + b; } ​ int (*fp)(int, int) = add; // fp 是函数指针 int result = fp(3, 4); // 通过指针调用,结果 7

声明语法

返回类型 (*指针名)(参数类型列表)
void (*callback)(int); // 指向 void func(int) 的指针 int (*compare)(const void*, const void*); // 指向比较函数的指针

实际用途:回调函数

函数指针最常见的用途是回调——把一个函数传给另一个函数:

// 排序时传入比较函数 int cmp(const void *a, const void *b) { return *(int*)a - *(int*)b; } ​ int arr[] = {3, 1, 4, 1, 5}; qsort(arr, 5, sizeof(int), cmp); // cmp 就是回调函数

qsort不知道你要怎么排序,你通过函数指针告诉它。

指针数组

指针数组:数组的每个元素是指针。

int a = 1, b = 2, c = 3; int *arr[3] = {&a, &b, &c}; // 3 个 int* 指针 ​ printf("%d\n", *arr[0]); // 1 printf("%d\n", *arr[1]); // 2

最常见用途:存储多个字符串

char *names[] = {"Alice", "Bob", "Charlie"}; printf("%s\n", names[0]); // "Alice" printf("%s\n", names[1]); // "Bob"

每个char *指向一个字符串常量。比二维数组灵活——字符串长度可以不同。

main 的命令行参数

int main(int argc, char *argv[]) { // argc: 参数个数 // argv: 指针数组,每个元素是一个字符串 for (int i = 0; i < argc; i++) { printf("%s\n", argv[i]); } return 0; }

运行./program hello world

./program hello world

指针数组 vs 数组指针

int *p[5]; // 指针数组:5 个 int* 组成的数组 int (*p)[5]; // 数组指针:指向含 5 个 int 的数组的指针

判断方法:[]优先级高于*,看*先跟谁结合。

  • *p[5]p先跟[5](数组),再跟*(指针)→ 指针数组

  • (*p)[5]:括号让*先跟p(指针),再跟[5](数组)→ 数组指针

常见误区速查

误区正确理解
p + 1加 1 字节加 1 个元素大小
指针相减得字节数得元素个数
不同数组指针可以相减未定义行为
3[p]是语法错误合法但别用
函数指针很少用回调函数、qsort 等场景常见

总结

  • 指针加减整数按元素大小缩放

  • 指针相减结果是元素个数,只对同数组有效

  • p[3]*(p+3)3[p](最后一种别用)

  • 函数指针存函数地址,常见于回调函数

  • 指针数组常见于存储多个字符串和命令行参数

  • 指针数组int *p[5]和数组指针int (*p)[5]不同

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/21 12:15:57

漏洞挖掘方法论:从信息收集到代码审计的全流程实战解析

1. 从“黑盒”到“白盒”&#xff1a;漏洞挖掘的核心方法论全景每次看到新闻里爆出某个知名系统被曝出高危漏洞&#xff0c;或者某个安全研究员在顶级会议上分享一个精妙的利用链&#xff0c;我猜很多人心里都会闪过一个念头&#xff1a;这些漏洞挖掘高手&#xff0c;到底是怎么…

作者头像 李华
网站建设 2026/6/21 12:15:48

基于A71CH安全芯片的物联网设备硬件防伪认证方案详解

1. 项目概述与核心价值在物联网设备大规模部署的今天&#xff0c;防伪与身份认证已经从一个“加分项”变成了“生存项”。想象一下&#xff0c;你是一家智能门锁或工业传感器的制造商&#xff0c;如果市面上出现了大量仿冒品&#xff0c;不仅会侵蚀你的市场份额&#xff0c;更可…

作者头像 李华
网站建设 2026/6/21 12:13:18

如何在3小时内掌握yuzu模拟器:Switch游戏PC畅玩完整指南

如何在3小时内掌握yuzu模拟器&#xff1a;Switch游戏PC畅玩完整指南 【免费下载链接】yuzu 任天堂 Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/yu/yuzu 想在电脑上体验任天堂Switch游戏的魅力吗&#xff1f;yuzu模拟器是你实现这一梦想的最佳选择。作…

作者头像 李华
网站建设 2026/6/21 12:11:05

WaveTools鸣潮工具箱终极指南:如何免费解锁帧率与优化游戏性能

WaveTools鸣潮工具箱终极指南&#xff1a;如何免费解锁帧率与优化游戏性能 【免费下载链接】WaveTools &#x1f9f0;鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools WaveTools鸣潮工具箱是一款专为《鸣潮》PC玩家设计的免费开源辅助工具&#xff0…

作者头像 李华
网站建设 2026/6/21 12:10:19

告别游戏崩溃!Reloaded-II终极指南:零基础打造稳定mod环境

告别游戏崩溃&#xff01;Reloaded-II终极指南&#xff1a;零基础打造稳定mod环境 【免费下载链接】Reloaded-II Universal .NET Core Powered Modding Framework for any Native Game X86, X64. 项目地址: https://gitcode.com/gh_mirrors/re/Reloaded-II 你是否曾经因…

作者头像 李华
网站建设 2026/6/21 12:04:06

TWR-SENSOR-PAK传感器评估套件:模块化设计与嵌入式开发实战

1. 项目概述与核心价值 在嵌入式开发和物联网设备原型设计的早期阶段&#xff0c;如何快速、高效地评估和集成多种传感器&#xff0c;往往是决定项目进度的关键。传统方式下&#xff0c;工程师需要为每一种传感器单独设计电路板、编写驱动、调试接口&#xff0c;这个过程不仅耗…

作者头像 李华