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

关于我、重生到500年前凭借C语言改变世界科技vlog.13——深入理解指针(3)

文章目录

  • 1.字符指针变量
  • 2.数组指针变量
  • 3.函数指针变量
  • 4.函数指针数组
  • 5.二维数组传参本质
  • 6.拓展补充
  • 希望读者们多多三连支持
  • 小编会继续更新
  • 你们的鼓励就是我前进的动力!

本章节接着学习常见的指针变量类型

1.字符指针变量

字符指针变量,顾名思义就是字符类型的指针,即 char*
常见的输出格式是这样的:

int main()
{char ch = 'w';char *pc = &ch;*pc = 'w';return 0;
}

这是存放一个字符的情况,如果存放字符串呢?

int main()
{const char* pstr = "hello bit.";printf("%s\n", pstr);return 0;
}

乍一看是存放字符串在指针变量中,但我们要记住指针变量是用来存放地址的
所以这里本质是把字符串 hello bit. 首字符的地址放到了pstr中,即字符 h 的地址

2.数组指针变量

上一篇 vlog 学到了指针数组,就是存放指针的数组,也可以理解为存放指针的集合(元素相同),那么数组指针就可以得出是存放数组地址的指针,是一种指针变量,指向数组

int *p1[10];
int (*p2)[10];

那么以上哪种是数组指针?
答案是下面那个
分析:[ ] 的优先级大于 * ,所以必须加上 [ ] 来保证 p 和 * 优先结合

p先和 * 结合,说明p是一个指针变量,然后指针指向的是一个大小为10个整型的数组
所以 p 是一个指针,指向一个数组,叫数组指针

int 表示 p指向的数组的元素类型, p 是数组指针变量名,10是指向数组的元素个数

3.函数指针变量

根据前面学过的类比,不难发现,函数指针变量应该是用来存放函数地址的,通过地址能够调用函数的
那么函数真的有地址吗?

#include <stdio.h>
void test()
{printf("hehe\n");
}
int main()
{printf("test: %p\n", test);printf("&test: %p\n", &test);return 0;
}

通过以上代码可以发现函数确实有地址,用函数名就能代表其地址,当然也可以通过 &函数名 的方
式获得函数的地址,为了方便一般就不写取地址符
其语法形式为:

int(*pf3)(int, int) = Add;
int(*pf3)(int x, int y) = &Add;

函数参数的变量名可写可不写,取地址符也是
int 是指向函数的返回类型,pf3 是函数指针变量名,int x,int y 是 pf3 指向函数的参数类型和个数

#include <stdio.h>
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));return 0;
}

可以将通过函数指针调用指针指向的函数写一个我们之前写过的加法函数

这里通过解引用函数指针 pf3 的方式来调用它所指向的函数(也就是 Add 函数),传入参数 2 和 3,然后将返回的结果使用 printf
函数输出。实际上,在这种情况下,解引用操作符 * 在这里是可选的,因为在 C
语言中,函数名本身在求值时就会转换为指向该函数的指针,所以也可以直接写成 pf3(2, 3)

4.函数指针数组

在学习了指针数组的基础上,我们引入函数指针放入数组
那么以下哪种为正确的形式?

int (*parr1[3])();
int *parr2[3]();
int (*)() parr3[3];

答案是第一个

定义形式如下:返回值类型 (*数组名[数组大小])(参数列表)

parr1 先和 [ ] 结合,说明 parr1是数组,是 int (*)() 类型的函数指针
那么参数如何理解?其实就是每个元素代表的函数

#include <stdio.h>int add(int a, int b) {return a + b;
}int subtract(int a, int b) {return a - b;
}int main() {int (*func_array[2])(int, int) = {add, subtract};return 0;
}

在上述代码中,func_array 数组的两个元素分别被初始化为 add 函数和 subtract 函数的指针

5.二维数组传参本质

讲数组的时候说过二维数组其实可以看做是每个元素是一维数组的数组,也就是二维数组的每个元素是一个一维数组,那么二维数组的首元素就是第一行,是个一维数组
在这里插入图片描述
第一行的一维数组的类型就是 int [5] ,所以第一行的地址的类型就是数组指针类型 int(*)[5] ,那就意味着二维数组传参本质上也是传递了地址,传递的是第一行这个一维数组的地址,那么形参也是可以写成指针形式的,总的来说就是把二维数组当一维数组理解,第一行看成一维数组的第一个元素,首元素就是第一行一整行的地址

#include <stdio.h>void test(int (*p)[5], int r, int c){int i = 0;int j = 0;for(i=0; i<r; i++){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}};test(arr, 3, 5);return 0;
}

普通的遍历数组传参也可以这样写

这里的 *(p+i) 相当于获取二维数组的第 i 行的首地址(因为 p 是指向包含 5 个整数的数组的指针,p+i 就指向了第 i 行),然后 *(p+i)+j 就是指向第 i 行第 j 列元素的指针,最后 ((p+i)+j) 就是获取该位置的元素值并输出

虽然解引用通常是获取元素本身,但在指向二维数组行的指针这种特殊情况下,由于指针所指向的对象本身就是一个数组,解引用得到的就是这个数组的首地址,这是由 C 语言的指针和数组特性共同决定的

二维数组传参,形参的部分可以写成数组,也可以写成指针形式

6.拓展补充

补充一个关键字 typedef ,是用来类型重命名的,可以将复杂的类型,简单化

普通类型

typedef unsigned int uint;
//将unsigned int 重命名为uint

普通指针类型

typedef int* ptr;

数组函数指针类型

typedef int(*parr)[5]; //新的类型名必须在*的右边
typedef void(*pfun)(int);//新的类型名必须在*的右边

下一期 vlog 将对二分查找,转移表,冒泡排序等常见算法题目进行练习解析
建议对前面的知识都有系统性的理解后再来写题

主页传送门:DARLING Zero two♡ 的 blog

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

在这里插入图片描述

相关文章:

关于我、重生到500年前凭借C语言改变世界科技vlog.13——深入理解指针(3)

文章目录 1.字符指针变量2.数组指针变量3.函数指针变量4.函数指针数组5.二维数组传参本质6.拓展补充希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&#xff01; 本章节接着学习常见的指针变量类型 1.字符指针变量 字符指针变量&#xff0c;顾名思义就是字…...

每日算法一练:剑指offer——数组篇(6)

1.点名 某班级 n 位同学的学号为 0 ~ n-1。点名结果记录于升序数组 records。假定仅有一位同学缺席&#xff0c;请返回他的学号。 示例 1: 输入: records [0,1,2,3,5] 输出: 4示例 2: 输入: records [0, 1, 2, 3, 4, 5, 6, 8] 输出: 7提示&#xff1a; 1 < records.le…...

【环境搭建】Apache ZooKeeper 3.8.4 Stable

软件环境 Ubuntu 20.04 、OpenJDK 11 OpenJDK 11&#xff08;如果已经安装&#xff0c;可以跳过这一步&#xff09; 安装OpenJDK 11&#xff1a; $ sudo apt-get update$ sudo apt-get install -y openjdk-11-jdk 设置 JAVA_HOME 环境变量&#xff1a; $ sudo gedit ~/.bash…...

算法练习——双指针

前言&#xff1a;大佬写博客给别人看&#xff0c;菜鸟写博客给自己看&#xff0c;我是菜鸟。 学前须知&#xff08;对自己&#xff09;&#xff1a;这里的指针不一定指地址&#xff01;也可能是数组下标。 1&#xff1a;移动零(双指针) 题目要求&#xff1a; 解题思路&#x…...

vue中el-table显示文本过长提示

1.el-table设置轻提示:show-overflow-tooltip“true“&#xff0c;改变轻提示宽度...

JS 字符串拼接并去重

1、includes 循环数组将某个字段拼接成新的字符串并去重&#xff08;数组里面包含的一个对象&#xff0c;或者其他都OK&#xff09; // 定义一个数组 let arr[.......] // 定义拼接的字符串 let a //循环数组将里面某个字段拼接在一起并去重 arr.forEach(item > {if(!a.in…...

opencv 图像预处理

图像预处理 ​ 在计算机视觉和图像处理领域&#xff0c;图像预处理是一个重要的步骤&#xff0c;它能够提高后续处理&#xff08;如特征提取、目标检测等&#xff09;的准确性和效率。OpenCV 提供了许多图像预处理的函数和方法&#xff0c;以下是一些常见的图像预处理操作&…...

SAP B1 功能模块字段介绍 - 价格清单(下)

目录 背景 五、业务伙伴的特殊价格 1. 单据逻辑功能 2. 部分字段解释 3. 操作流程 3.1 时间相关 3.2 数量相关 4. 实例 六、复制特殊价格到选择标准 1. 单据逻辑功能 2. 部分字段解释 七、全局更新特殊价格 ​编辑 1. 单据逻辑功能 2. 部分字段解释 八、价格更…...

传智杯 第六届-复赛-D

题目描述&#xff1a; 小红定义两个字符串同构&#xff0c;当且仅当对于i∈[1,n],b[i]−a[i]i∈[1,n],b[i]-a[i]i∈[1,n],b[i]−a[i]是定值。例如&#xff0c;"bacd"和"edfg"是同构的。 现在小红拿到了一个长度为n的字符串a&#xff0c;她想知道&a…...

Java - 数组实现大顶堆

题目描述 实现思路 要实现一个堆&#xff0c;我们首先要了解堆的概念。 堆是一种完全二叉树&#xff0c;分为大顶堆和小顶堆。 大顶堆&#xff1a;每个节点的值都大于或等于其子节点的值。 小顶堆&#xff1a;每个节点的值都小于或等于其子节点的值。 完全二叉树&#xff…...

ifuse挂载后,在python代码中访问iOS沙盒目录获取app日志

上一次使用pymobiledevice3&#xff0c;在python代码中访问app的沙盒目录并分析业务日志&#xff0c;在使用过程中发现&#xff0c;在获取app日志的时候速度很慢&#xff0c;执行时间很长&#xff0c;需要30-61秒&#xff0c;所以这次尝试使用libimobiledevic和ifuse&#xff0…...

Windows WSL环境下安装 pytorch +ROCM 支持AMD显卡

官方文档&#xff1a;Install PyTorch for ROCm — Use ROCm on Radeon GPUs 一、操作系统及驱动 windows 下安装WSL 环境( windows subsystem for Linux), 安装ubuntu 22.04环境。 安装 rocm 软件包&#xff1a; sudo apt update wget https://repo.radeon.com/amdgpu-insta…...

uniapp中skymap.html(8100端口)提示未登录的排查与解决方法

问题&#xff1a; 目前账号已经登录&#xff0c;uniapp的其他端口均可以访问到数据&#xff0c;唯独skymap.html中的8100会提示未登录。&#xff08;8100是后端网关gateway端口&#xff09; 分析&#xff1a; 在 skymap.html 中遇到未登录提示的问题&#xff0c;通常是由于该…...

训练模型时梯度出现NAN或者INF(禁用amp的不同level)

判断参数梯度位nan或inf的代码&#xff1a; for name, param in model.named_parameters():if param.grad is not None:if torch.isnan(param.grad).any() or torch.isinf(param.grad).any():print(f"grad layer [{name}] is NaN or Inf") 首先来说可能得原因&…...

Maven核心概念

一、项目对象模型&#xff08;POM&#xff09; 1. 定义 POM&#xff08;Project Object Model&#xff09;是 Maven 项目的核心配置文件&#xff0c;它以 XML 格式描述了项目的基本信息、项目依赖、构建配置等。可以说&#xff0c;POM 是 Maven 理解和处理项目的基础。 2. 基…...

Sonatype Nexus 部署手册

文章目录 一、前言二、软件环境2.1 版本变更&#xff1a;2.1.1 变更存储的原因2.2.2 H2作为存储的注意点 三、资源配置四、开始部署4.1 部署jdk174.2 离线部署nexus4.2.1 下载4.2.2 部署1. 上传到服务器2. 解压3. 添加用户4. 修改启动参数5. 迁移sonatype-work &#xff0c;并授…...

TLV320AIC3104IRHBR 数据手册 一款低功耗立体声音频编解码器 立体声耳机放大器芯片麦克风

TLV320AIC3104 是一款低功耗立体声音频编解码器&#xff0c;具有立体声耳机放大器以及在单端或全差分配置下可编程的多个输入和输出。该器件包括基于寄存器的全面电源控制&#xff0c;可实现立体声 48kHz DAC 回放&#xff0c;在 3.3V 模拟电源电压下的功耗低至 14mW&#xff0…...

(8)结构体、共用体和枚举类型数据

1. 结构体、共用体的定义及区别,typedef 定义别名 结构体的定义 结构体是一种用户自定义的数据类型,它可以将不同类型的数据组合在一起。例如,定义一个表示学生信息的结构体: // 定义结构体类型 struct Student struct Student {char name[20];int age;float score; };共…...

Jedis操作和springboot整合redis

Jedis-springboot整合redis Jedis 引入jedis依赖 注意事项 测试相关数据类型 Key String List set hash zset 案例 spring boot整合redis 引入相关依赖 在application.properties中配置redis 配置 创建redis配置类 创建测试类 Jedis 引入jedis依赖 <depen…...

基于AI大模型的复杂扫描件PDF信息提取与规整

前言 场景大致是会上传一个几十页的扫描件PDF&#xff0c;让AI在当中找出我需要的字段&#xff0c;本文会隐去具体行业信息和具体的AI提示词内容&#xff0c;只分享技术相关内容&#xff0c;请见谅。 AI模型选择 针对我们行业的使用场景&#xff0c;我主要测试了GPT、Claude以…...

为什么https先非对称加密,然后对称加密?

HTTPS之所以先使用非对称加密&#xff0c;然后在对称加密&#xff0c;主要是基于两者在加密效率与安全性方面的特性考虑。 首先&#xff0c;非对称加密具有极高的安全性&#xff0c;因为它使用了公钥和私钥这一对密钥。公钥是公开的&#xff0c;任何人都可以使用它来加密数据&…...

【Coroutines】Full Understanding of Kotlinx.Corutines Framework

文章目录 What is CorutinesDifference between Corutine and ThreadFast UsageSuspend FunctionAdvanced Usage of CoroutineCoroutine EssentialsCoroutineContextCoroutineScopePredefined CoroutineScopePredefined DispatchersPredefined CoroutineStartJobCreate a Corou…...

Python面向对象,实现图片处理案例,支持:高斯模糊、Canny边缘检测、反转边缘图像、生成手绘效果、调亮度......等等

实验图片如下&#xff1a; 命名为img1.jpg, 放在项目下新建文件夹images下 项目构造如下&#xff1a; app.py源码如下 import cv2 import os from matplotlib import pyplot as plt import numpy as npclass ImageProcessor:def __init__(self, image_path):self.image cv…...

SOLID - 依赖倒置原则(Dependency Inversion Principle)

SOLID - 依赖倒置原则&#xff08;Dependency Inversion Principle&#xff09; 定义 依赖倒置原则&#xff08;Dependency Inversion Principle&#xff0c;DIP&#xff09;是面向对象设计中的五大基本原则之一&#xff0c;通常缩写为SOLID中的D。DIP由Robert C. Martin提出&…...

【.NET 8 实战--孢子记账--从单体到微服务】--需求拆分与规划

在上一篇文章中我们收集了需求&#xff0c;并对需求进行了简单的分析和规划&#xff0c;但是对于开发人员来说&#xff0c;上一篇文章的需求还不够详细&#xff0c;并且没有形成计划。因此本篇文章将带领大家来拆分需求并规划开发里程碑。 一、详细需求列表 项目组进行了多次…...

在macOS的多任务处理环境中,如何平衡应用的性能与用户体验?这是否是一个复杂的优化问题?如何优化用户体验|多任务处理|用户体验|应用设计

目录 一 多任务处理与应用性能 1. macOS中的多任务处理机制 2. 性能优化的基本策略 二 用户体验的关键要素 1. 响应速度 2. 界面友好性 3. 功能的直观性 三 平衡性能与用户体验的策略 1. 资源管理 2. 优化数据加载 3. 使用合适的线程模型 4. 实时监测和调整 四 使…...

Vscode配置CC++编程环境的使用体验优化和补充说明

文章目录 快速编译运行&#x1f47a;code runner插件方案Code Runner Configuration 直接配置 相关指令和快捷键默认task配置和取消默认 配置文件补充介绍(可选 推荐阅读)&#x1f60a;使用vscode预置变量和环境变量环境变量的使用使用环境变量的好处环境变量可能引起的问题 检…...

十个方法杜绝CAD图纸泄密风险!2024年图纸防泄密指南!「必看」

随着信息技术的发展&#xff0c;CAD图纸的应用日益普遍&#xff0c;然而随之而来的图纸泄密风险也愈加严重。企业在提升效率的同时&#xff0c;更需重视信息安全。为此&#xff0c;本文将介绍十个有效的方法&#xff0c;帮助企业杜绝CAD图纸泄密风险&#xff0c;保障商业机密。…...

技术干货|HyperMesh CFD功能详解:虚拟风洞 Part 1

虚拟风洞VWT 从2023版本开始&#xff0c;虚拟风洞VWT&#xff08;Virtual Wind Tunnel&#xff09;模块合并到HyperMesh CFD中。 用户在VWT模块中完成LBM求解器ultraFluidX的前处理设置&#xff0c;导出参数文件XML和模型文件STL&#xff0c;并在GPU服务器上提交计算。 VWT目前…...

022集——统计多条线的总长度(CAD—C#二次开发入门)

如下图所示&#xff0c;选择多条线并统计长度&#xff1a; c#中不包含直接获取curve曲线长度 属性&#xff0c;需用如下方法&#xff1a;curve.GetDistanceAtParameter(item.EndParam) 附部分代码如下&#xff1a; using Autodesk.AutoCAD.ApplicationServices; using Autode…...