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

嵌入式开发学习日志() day14 持续更新中

一、指针数组

1. 什么是“指针数组”?

本质:它是一个数组。
特点:该数组中保存的每一个元素都是指针(地址)。

2. 定义语法

int *a[5];
  • int *:表示数组中保存的数据类型是int *(整型指针)。
  • [5]:表示该数组可以保存 5 个这样的指针。

3. 初始化方式

(1) 初始化为空
char *p = NULL; char *p[5] = {NULL}; // 将5个字符型指针全部初始化为 NULL
(2) 初始化指向字符串常量
char *p[5] = {"hello", "world", "how", "are", "you"};
  • p[0]保存字符串 "hello" 的首地址。
  • p[1]保存字符串 "world" 的首地址。
  • ...以此类推。

4. 内存模型图解

当我们执行char *p[5] = {"hello", ...};时,内存布局如下:

  • 左侧(栈区):p数组本身存储的是一个个地址(如0x5000,0x3000等)。
  • 右侧(字符串常量区):真正的字符串数据存储在只读区域,数组中的指针指向它们。

5. 重点辨析:指针数组 vs 二维字符数组

这是面试和考试中的高频考点:

// 二维字符数组 char str[3][100] = {"hello", "world", "how"}; sizeof(str) == 300 字节 // 3 * 100 // 指针数组 char *pstr[3] = {"hello", "world", "how"}; sizeof(pstr) == 24 字节 // 64位系统下 3 * 8

区别总结:

  1. 存储内容不同:二维数组保存的是字符串本身(拷贝了一份);指针数组保存的是字符串的首地址(引用)。
  2. 空间效率:如果要保存多个长度不一的字符串,使用指针数组更节省空间且操作更灵活。

二、二级指针

1. 什么是“二级指针”?

本质:它还是一个指针。
含义:它是一个“指向指针的指针”,即保存的是另一个指针变量的地址。

  • int **p:保存整型指针的地址。
  • char **p:保存字符型指针的地址。

2. 两大核心应用场景

  1. 修改主调函数中的指针变量:如果你想在被调函数中修改主调函数里定义的指针变量(例如让指针指向新的内存),必须传递该指针的地址(即二级指针)。
  2. 接收指针数组的数组名:指针数组的数组名在作为参数传递时,本质上就是一个二级指针。
char *str[3] = {"hello", "world", "how"}; // str 的类型就是 char **

3. 传参机制图解(值传递 vs 地址传递)

理解二级指针的关键在于理解 C 语言的函数传参机制。

(1) 普通变量的传递
  • 值传递:fun(n)-> 无法修改主调函数的n
  • 地址传递(一级指针):fun(&n)-> 可以修改主调函数的n
(2) 指针变量的传递
  • 值传递(传一级指针):

    void fun(char *pstr) { pstr = "world"; } // 仅修改了形参,实参不变

    结果:主调函数中的指针依然指向 "hello"。

  • 地址传递(传二级指针):

    void fun(char **pstr) { *pstr = "world"; } // 通过解引用,修改了实参指向的内容

    结果:主调函数中的指针被成功修改为指向 "world"。


三、指针函数

1. 概念

本质:它是一个函数。
定义:返回值类型是指针类型的函数。

2. 返回值的注意事项(避坑指南)

指针函数能返回什么样的指针?这是一个关于生命周期的问题。

  • 绝对不能返回:局部变量的地址(局部变量、局部数组)。因为函数结束后,栈内存被释放,返回的地址将变成野指针。

    char str[32] = "hello world"; // 局部数组 return str; // 错误!
  • 可以安全返回:

    1. static修饰的静态变量地址(生命周期贯穿程序始终)。
    2. 全局变量的地址。
    3. 字符串常量的地址(如return "hello world",存储在只读区)。
    4. 通过参数传递进来的地址(如strcpy返回dest)。
    5. 通过malloc在堆区申请且未被free的空间。

四、函数指针

1. 概念

本质:它是一个指针。
含义:指向函数的指针。函数名本身就是函数的入口地址。

2. 语法辨析

这是最容易混淆的地方,请注意括号的位置:

  • 函数声明:int fun(int, int);—— 声明一个名为 fun 的函数。
  • 指针函数:int *fun(int, int);—— 声明一个名为 fun 的函数,返回值是 int*。
  • 函数指针:int (*pfun)(int, int);—— 定义一个名为 pfun 的指针,指向参数为两个 int、返回值为 int 的函数。

总结口诀:看到(*名称),它就是指针;看到*名称(),它就是函数。

3. 使用步骤

  1. 定义:int (*pfun)(int, int) = NULL;(通常占 4 或 8 字节)。
  2. 赋值:
    int add(int n1, int n2) { ... } pfun = add; // 或者 pfun = &add;
  3. 调用:
    pfun(1, 2); // 等价于 (*pfun)(1, 2);

4. 高级应用:回调函数

函数指针最大的威力在于回调函数

  • 定义:将函数作为参数传递给另一个函数。
  • 目的:降低代码耦合度,实现多态效果,减少重复代码(例如qsort排序函数就是通过回调函数来决定排序规则的)。
http://www.jsqmd.com/news/1337914/

相关文章:

  • OpenLayers WMTS加载天地图EPSG:4326瓦片与BD09坐标转换实战(07)
  • Voohu:SFP/SFP+连接器镀层厚度对接触电阻与高频插入损耗的协同影响
  • 宴席选白酒有哪些传统讲究和实用技巧办喜宴选白酒要注意哪些传统文化禁忌家宴选白酒有哪些习俗讲究和注意事项宴席上选白酒如何
  • 2026年最新教程:报名照片分辨率不符合怎么办的解决方法 - 图片处理研究员
  • GESP一级编程题解析:买文具的算法实现与教学应用
  • 2026 年新消息:汉阳本地楼道走廊墙体彩绘施工公司联系电话,老破小楼道秒变网红打卡点,这玩意儿居然不用花大价钱? - 行业严选官
  • Element Plus Timeline组件横向布局改造:CSS深度覆盖与响应式实践
  • 2026实测教程:手机压缩视频用什么小程序?其实转GIF更实用 - 玩机日常
  • 参数检验前必看:用偏度与峰度诊断数据正态性
  • XTX这颗1G SPI NAND换代了,一文看懂C版与D版的爱恨情仇!
  • MySQL安装与连接全攻略:从版本选择到实战连接
  • GD32F103实现SD卡USB大容量存储设备(MSC)与FATFS文件系统完整指南
  • 绿色工厂申报机构如何选型?智碳能碳管理平台:全流程交付与节点覆盖指南
  • 福建有实力的护肤品旗舰店选型与供应链对接指南 - 品牌优推
  • Hi3519DV500嵌入式Wi-Fi驱动开发:内核配置、设备树与调试实战
  • 基于OpenClaw与钉钉构建企业级AI助手:从架构设计到技能开发实战
  • 成都彩盒定制厂家怎么选?2026年本地口碑包装企业参考指南 - 优质品牌商家
  • 同一批Prompt如何对比多个教师模型:蒸馏数据小样本评测方法
  • 2026年最新教程:照片分辨率怎么调到 300dpi 亲测可用方法 - 图片处理研究员
  • Cocos2dx-js游戏资源逆向实战:解密.jsc与反编译.pkm纹理
  • 改造Claude Desktop:打造支持多模型与中文界面的AI聚合桌面客户端
  • OpenClaw模型降级配置实战:保障AI服务高可用性的关键策略
  • 入局自营交易5步流程:从平台筛选到长期进阶,带你快速了解自营玩法
  • ESP8266透传模式退出难题与网络数据获取实战指南
  • 2026 年新消息:连山壮族瑶族自治值得关注的帮我推荐一个好用的短视频获客软件商家哪家强,想做短视频获客却踩坑不断?这玩意儿真能帮中小商家精准拉客?-抖成豆包推广 - 行业推荐官[官方】--
  • STM32时钟配置实战:从原理到避坑,CubeMX配置全解析
  • 2026年上海发动机水温高治理与老车养护服务参考指南 - 优质品牌商家
  • Kafka控制器深度解析:集群大脑的选举、职责与运维实战
  • 2026 年现阶段,清远值得关注的笼车托运服务团队哪家可靠,你还在为大件运输头疼?这款省心省力的它,帮你避开90%的踩坑风险 - 企业推荐官【认证】
  • CAD机械制图入门:圆弧绘制核心技巧与实战应用