C语言学习记录——深入理解指针(4)

     OK,这一篇主要是讲我学习的3种指针类型。

正文开始:

一.字符指针

    所谓字符指针,顾名思义就是指向字符的指针。一般写作  " char* "

直接来说说它的使用方法吧:

(1)一般使用情况:

int main()
{char a = 'A';char* p = &a;//取出a的地址printf("%c\n", *p);return 0;
}

打印结果:

(2)特殊使用情况:

int main()
{char s[] = "hello world";const char* p = s;printf("%s\n", p);return 0;
}

先看看运行情况:

这里是创建了一个字符数组写的字符串,然后用p接收了字符串首字符的地址。  注意喔,这里不是p接收了整个字符串的地址,这里打印出整个字符串容易让人误会是p接收了整个字符串的地址,实际上是因为打印字符串有首元素的地址就可以全部打印了。

验证一下:

这里就可以看出,这里p和字符串首元素的地址是一模一样的

好的,字符指针结束。
 

二.数组指针

   我之前还学习过指针数组,刚开始经常把它与数组指针搞混淆,这两者是完全不一样的,指针数组是存放指针的数组,而数组指针是指向数组的指针。也就是说,数组指针是指针变量

我们已经熟悉:

• 整形指针变量: int * pint; 存放的是整形变量的地址,能够指向整形数据的指针。

• 浮点型指针变量: float * pf; 存放浮点型变量的地址,能够指向浮点型数据的指针。

那数组指针变量应该是:存放的应该是数组的地址,能够指向数组的指针变量。

   

答案是第二个,因为在第一个语句中  []  的优先级比   *   更高 ,会优先与p1结合,所以必须用()像(*p2)这样括在一起。那么p2先和*结合,说明p2是⼀个指针变量,然后指针指向的是⼀个⼤⼩为10个整型的数组。所以p2是 ⼀个指针,指向⼀个数组,叫 数组指针。

好的,接下来介绍一下数组指针的用法。

(1)数组指针的初始化:

int main()
{int arr[10] = { 0 };&arr;//取出arr的地址。int (*p)[10] = &arr;return 0;
}

这里就取出了整个数组的地址(&arr)保存到数组指针 p 中

我们调出监视查看:

可以发现arr和p的类型是完全一样的。

那我们就可以得到下面的结论:

(2)二维数组传参的本质

   知道了数组指针的概念,就可以讲一下数组传参的本质了。

我之前写二维数组传参代码是这样写的:

void func(int arr[3][5], int r, int c)
{int i = 0;for (i = 0;i < r;i++){int j = 0;for (j = 0;j < c;j++){printf("%d ", arr[i][j]);}printf("\n");}
}int main()
{int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };func(arr, 3, 5);return 0;
}

可以看到形参接收的时候也是使用(arr[3][5])这样的二维数组的形式来接受的,那当我学习了数组名是数组首元素的地址和数组指针后我知道了一种新的写法。

⾸先我们再次理解⼀下⼆维数组,⼆维数组其实可以看做是每个元素是⼀维数组的数组,也就是⼆维数组的每个元素是⼀个⼀维数组。那么⼆维数组的⾸元素就是第⼀⾏,是个⼀维数组

如下图:

所以,根据数组名是数组⾸元素的地址这个规则,⼆维数组的数组名表⽰的就是第⼀⾏的地址,是⼀ 维数组的地址。根据上⾯的例⼦,第⼀⾏的⼀维数组的类型就是 int [5] ,所以第⼀⾏的地址的类 型就是数组指针类型 int(*)[5] 。那就意味着⼆维数组传参本质上也是传递了地址,传递的是第⼀ ⾏这个⼀维数组的地址,那么形参也是可以写成指针形式的。如下:

void func(int(*p)[5], int r, int c)
{int i = 0;for (i = 0;i < r;i++){int j = 0;for (j = 0;j < c;j++){printf("%d ", *(*(p+i)+j));}printf("\n");}
}int main()
{int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };func(arr, 3, 5);return 0;
}

形参就用数组指针来接收,打印也用解引用地址来打印,

printf("%d ", *(*(p+i)+j));

这一行可能不太好理解,本人也没那个能耐就用文字说清楚,不懂的朋友可以用AI去解释,只要熟悉指针了,那还是很好理解的。

好的,数组指针就到这里。

三.函数指针

   接下来就是最后的函数指针了。

那么什么是函数指针变量呢? 根据前⾯学习整型指针,数组指针的时候,我们的类⽐关系,我们不难得出结论: 函数指针变量应该是⽤来存放函数地址的,未来通过地址能够调⽤函数的。 那么函数是否有地址呢?

很简单,做个测试就知道了。

测试出来函数果然也是有地址的,并且使用(函数名)和使用(&函数名)打印出来的地址是一样的,这和数组有点像,但不同的是:  数组名!= &数组名,但是 函数名==&函数名,也就是说,函数比数组还好记一点。

那么初始化函数指针的方式也就类比着数组的来:

int Add(int x, int y)
{return x + y;
}
int main()
{int(*pf1)(int, int) = Add;
int(*pf2)(int x, int y) = &Add;//x和y写上或者省略都是可以的return 0;
}

这就把函数(Add)的地址保存到指针变量(pf)中了。

接下来是使用函数指针变量,毕竟初始化了肯定要使用一下的嘛。

int Add(int x, int y)
{return x + y;
}
int main()
{int(*pf3)(int, int) = Add;printf("%d\n", (*pf3)(2, 3));//使用函数指针来调用函数printf("%d\n", pf3(3, 5));//(*pf3)==pf3,不需要使用*符号return 0;
}

注意看我写在代码中的注释,运行结果如下:

这下函数指针的调用也学会了。

四.最后

不知不觉写了两个多小时了,学习的时间过得很快,希望现在和未来学的技术都能够让我在以后获得收获吧。

应该……会的吧,管他呢,反正有问题就解决,人生不就是被问题堆起来的嘛,不出现问题人生反而会有些索然无味吧。

说多了也说偏了,总之谢谢大家的阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/80753.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot3+vue3融合项目实战-大事件文章管理系统获取用户详细信息-ThreadLocal优化

一句话本质 为每个线程创建独立的变量副本&#xff0c;实现多线程环境下数据的安全隔离&#xff08;线程操作自己的副本&#xff0c;互不影响&#xff09;。 关键解读&#xff1a; 核心机制 • 同一个 ThreadLocal 对象&#xff08;如示意图中的红色区域 tl&#xff09;被多个线…

Nacos源码—8.Nacos升级gRPC分析六

大纲 7.服务端对服务实例进行健康检查 8.服务下线如何注销注册表和客户端等信息 9.事件驱动架构源码分析 一.处理ClientChangedEvent事件 也就是同步数据到集群节点&#xff1a; public class DistroClientDataProcessor extends SmartSubscriber implements DistroDataSt…

设计杂谈-工厂模式

“工厂”模式在各种框架中非常常见&#xff0c;包括 MyBatis&#xff0c;它是一种创建对象的设计模式。使用工厂模式有很多好处&#xff0c;尤其是在复杂的框架中&#xff0c;它可以带来更好的灵活性、可维护性和可配置性。 让我们以 MyBatis 为例&#xff0c;来理解工厂模式及…

AI与IoT携手,精准农业未来已来

AIoT&#xff1a;农业领域的变革先锋 在科技飞速发展的当下&#xff0c;人工智能&#xff08;AI&#xff09;与物联网&#xff08;IoT&#xff09;的融合 ——AIoT&#xff0c;正逐渐成为推动各行业变革的关键力量&#xff0c;农业领域也不例外。AIoT 技术通过将 AI 的智能分析…

排错-harbor-db容器异常重启

排错-harbor-db容器异常重启 环境&#xff1a; docker 19.03 , harbor-db(postgresql) goharbor/harbor-db:v2.5.6 现象&#xff1a; harbor-db 容器一直restart&#xff0c;查看日志发现 报错 initdb: error: directory "/var/lib/postgresql/data/pg13" exists…

Docker容器启动失败?无法启动?

Docker容器无法启动的疑难杂症解析与解决方案 一、问题现象 Docker容器无法启动是开发者在容器化部署中最常见的故障之一。尽管Docker提供了丰富的调试工具&#xff0c;但问题的根源往往隐藏在复杂的配置、环境依赖或资源限制中。本文将从环境变量配置错误这一细节问题入手&am…

查看购物车

一.查看购物车 查看购物车使用get请求。我们要查看当前用户的购物车&#xff0c;就要获取当前用户的userId字段进行条件查询。因为在用户登录时就已经将userId封装在token中了&#xff0c;因此我们只需要解析token获取userId即可&#xff0c;不需要前端再传入参数了。 Control…

C/C++ 内存管理深度解析:从内存分布到实践应用(malloc和new,free和delete的对比与使用,定位 new )

一、引言&#xff1a;理解内存管理的核心价值 在系统级编程领域&#xff0c;内存管理是决定程序性能、稳定性和安全性的关键因素。C/C 作为底层开发的主流语言&#xff0c;赋予开发者直接操作内存的能力&#xff0c;却也要求开发者深入理解内存布局与生命周期管理。本文将从内…

使用Stable Diffusion(SD)中CFG参数指的是什么?该怎么用!

1.定义&#xff1a; CFG参数控制模型在生成图像时&#xff0c;对提示词&#xff08;Prompt&#xff09;的“服从程度”。 它衡量模型在“完全根据提示词生成图像”和“自由生成图像”&#xff08;不参考提示词&#xff09;之间的权衡程度。 数值范围&#xff1a;常见范围是 1 …

【GESP】C++三级练习 luogu-B2156 最长单词 2

GESP三级练习&#xff0c;字符串练习&#xff08;C三级大纲中6号知识点&#xff0c;字符串&#xff09;&#xff0c;难度★★☆☆☆。 题目题解详见&#xff1a;https://www.coderli.com/gesp-3-luogu-b2156/ 【GESP】C三级练习 luogu-B2156 最长单词 2 | OneCoderGESP三级练…

Linux网络基础 -- 局域网,广域网,网络协议,网络传输的基本流程,端口号,网络字节序

目录 1. 计算机网络背景 1.1 局域网 1.1.2 局域网的组成 1.2 广域网 1.1.2 广域网的组成 2. 初始网络协议 2.1 网络协议的定义和作用 2.2 网络协议的分层结构 2.2.1 OSI七层模型 2.2.2 TCP/IP 五层&#xff08;四层&#xff09;模型 3. 再识网络协议 3.1 为什么要有…

【PostgreSQL】超简单的主从节点部署

1. 启动数据库 启动主节点 docker run --name postgres-master -e POSTGRES_PASSWORDmysecretpassword -p 5432:5432 -d postgres启动从节点 docker run --name postgres-slave -e POSTGRES_PASSWORDmysecretpassword -p 5432:5432 -d postgres需要配置挂载的存储卷 2. 数据…

c#修改ComboBox当前选中项的文本

对于一个C#的Combobox列表&#xff0c;类型设置为下拉样式&#xff0c;不允许输入&#xff0c;只能选择&#xff0c;样子如下&#xff1a; 该控件的名字为 cbb1&#xff0c;如果要修改当前这个“A1区”的文件&#xff0c;则用如下方式&#xff1a; cbb1.Items[cbb1.SelectedInd…

Java设计模式之适配器模式:从入门到精通

适配器模式(Adapter Pattern)是Java中最常用的结构型设计模式之一,它像一座桥梁连接两个不兼容的接口,使得原本由于接口不兼容而不能一起工作的类可以协同工作。本文将全面深入地解析适配器模式,从基础概念到高级应用,包含丰富的代码示例、详细注释、使用场景分析以及多维对…

中国黄土高原中部XF剖面磁化率和粒度数据

时间分辨率&#xff1a;1000年 < x空间分辨率为&#xff1a;空共享方式&#xff1a;申请获取数据大小&#xff1b;35.75 KB数据时间范围&#xff1a;743-0 ka元数据更新时间&#xff1a;2023-08-15 数据集摘要 该数据集包括中国黄土高原中部XF剖面磁化率和粒度数据。将所有…

【Python训练营打卡】day23 @浙大疏锦行

test pipeline管道 知识回顾: 1. 转化器和估计器的概念 2. 管道工程 3. ColumnTransformer和Pipeline类 作业&#xff1a; 整理下全部逻辑的先后顺序&#xff0c;看看能不能制作出适合所有机器学习的通用pipeline 伪代码 # 适合所有机器学习的通用pipeline #伪代码 import p…

【android bluetooth 框架分析 02】【Module详解 13】【CounterMetrics 模块介绍】

1. CounterMetrics 介绍 CounterMetrics 模块代码很少&#xff0c; 我简单介绍一下。 // system/gd/metrics/counter_metrics.cc #define LOG_TAG "BluetoothCounterMetrics"#include "metrics/counter_metrics.h"#include "common/bind.h" #i…

QMK键盘固件配置详解

QMK键盘固件配置详解 前言 大家好&#xff01;今天给大家带来QMK键盘固件配置的详细指南。如果你正在DIY机械键盘或者想要给自己的键盘刷固件&#xff0c;这篇文章绝对不容错过。QMK是目前最流行的开源键盘固件框架之一&#xff0c;它允许我们对键盘进行高度自定义。接下来&a…

基于STM32、HAL库的DPS368XTSA1气压传感器 驱动程序设计

一、简介: DPS368XTSA1 是 InvenSense(TDK 集团旗下公司)生产的一款高精度数字气压传感器,专为需要精确测量气压和温度的应用场景设计。它具有超低功耗、高精度、快速响应等特点,非常适合物联网、可穿戴设备和无人机等应用。 二、硬件接口: DPS368XTSA1 引脚STM32L4XX 引…

因子分析——数学原理及R语言代码

正交因子分析 目的数学原理参数估计方法主成分法主因子法极大似然法 因子旋转模型检验因子得分加权最小二乘法回归法 代码实现注意事项例子 Reference 目的 FactorAnalysis的目的是从多个高度相关的观测变量中提取出少数几个LatentFactor&#xff0c;这些因子代表了变量背后的…