详解指针(进阶版)(1)
前言:总篇章分为(1)和(2),本篇内容包括:指针数组,数组指针,&数组名与数组名的区分
数组传参 ,函数指针,函数指针数组
part 1:指针数组
指针数组是存放指针的数组
int* arr1[10]; //整形指针的数组——数组10个元素,每个元素的类型是整型指针int*
char *arr2[4]; //一级字符指针的数组——数组4个元素,每个元素的类型是字符指针char*
char **arr3[5];//二级字符指针的数组——数组5个元素,每个元素的类型是二级字符指针
part 2:数组指针
数组指针是指向数组的指针
int (*p)[10]; 数组指针
解释:p先和*结合表明p是一个指针,指向一个数组,数组10个元素,每个元素的类型是int
数组指针的使用:比如打印一个二维数组
void print_arr(int(*arr)[5], int row, int col)
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){printf("%d ", arr[i][j]); // 或者: *(*(arr+i)+j) // 因为arr是二维数组第一行的地址,即arr指向了第一行// arr+i:可以指向二维数组的第i行,代表的是第i行的地址// *(arr+i)就可以得到第i行的数组名//比如 int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//int (* p)[10] = &arr;//p --- &arr//*p --- *&arr//*p --- arr}printf("\n");}
}
int main()
{int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };print_arr(arr, 3, 5);return 0;
}
我们知道数组指针中存放的是数组的地址
二维数组的数组名arr:数组名是数组首元素的地址,即二维数组的数组名是二维数组首元素的地址
二维数组的首元素是第一行,即第一行的一维数组
故而二维数组的数组名arr代表的是第一行的地址,即一个一维数组的地址,需要使用数组指针接收:int(*arr)[5]
辨析指针数组和数组指针:
int arr[5]; //数组
int *parr1[10]; // 整型指针数组 - parr1是一个数组,数组10个元素,每个元素的类型是int*
int (*parr2)[10]; // 整型数组指针 - parr2是指针,指向一个数组,数组10个元素,每个元素的类型是int
int (*parr3[10])[5]; // 存放整型数组指针的数组 - parr3是数组,10个元素,每一个元素都是数组指针
part 3: &数组名与数组名的区分
数组名在绝大部分情况下是数组首元素的地址
只有两个特殊情况下,数组名代表整个数组
特殊情况1:sizeof(数组名):此时的数组名代表整个数组,sizeof计算的是整个数组的大小
特殊情况2:&数组名:此时取出的是整个数组的地址
part 4: 数组传参
一维数组传参:
#include <stdio.h>
//数组形式接收
void test(int arr[])//ok
{}
void test(int arr[10])//ok
{}
//指针形式接收
void test(int *arr)//ok
{}void test2(int *arr[20])//ok
{}
void test2(int **arr)//ok - arr2是数组名,即数组首元素的地址,即int*的地址,一级指针的地址用二级指针接收
{}int main()
{int arr[10] = {0};int *arr2[20] = {0};test(arr);test2(arr2);
}
二维数组传参:
void test(int arr[3][5])//ok
{}
void test(int arr[][])//NO 行可以省略,列不能省略
{}
void test(int arr[][5])//ok
{}
void test(int *arr)//NO arr是二维数组的数组名,是二维数组首元素(即第一行的一维数组)的地址,需要使用数组指针接收
{}
void test(int* arr[5])//NO
{}
void test(int (*arr)[5])//ok
{}
void test(int **arr)//NO
{}
int main()
{int arr[3][5] = {0};test(arr);
}
part 5:函数指针
函数名和&函数名都是函数的地址
void test()
{printf("hehe\n");
}
存放以上函数地址的函数指针:void (*p)()
解读:p先和*结合,说明p是一个指针,p后面有()说明p指向一个函数,函数无参,返回类型是void
当有了函数地址后,要通过函数指针对函数进行调用,可以解引用也可以不解引用
比如:
int Add(int x, int y)
{return x + y;
}
int main()
{int (* pf)(int, int) = Add;//pf是一个函数指针,指向一个函数,两个参数都是int类型,返回类型也是int类型int ret = (*pf)(3, 5); int ret = Add(3, 5);int ret = pf(3, 5);
}
下面来阅读两个有趣的代码:
不要慌,我们慢慢分析:
代码1是对函数的调用
(* (void (*)()) 0 ) ();// void (*)()是一个函数指针类型,(类型)是强制类型转换
// 故而:
// 1 将0强制转换成void (*)()类型的函数指针
// 2 0地址处存放着一个函数,函数无参,返回类型是void
// 3 对0地址处的函数进行调用
代码2是函数的声明
void (*signal(int , void(*)(int)) )(int);
// signal后面跟着(),说明signal是一个函数,该函数的第一个参数是int类型,第二个参数是 void(*)(int)
// 除却signal(int , void(*)(int))以外,剩下的都是signal函数的返回类型:void(*)(int)
part 6:函数指针数组
函数指针数组存放的是函数指针
int (*p[10])()
解释:p先和[]结合,说明p十个数组,数组十个元素,
每个元素的类型都是函数指针:int (*)()
函数指针数组的使用例子:简易计算器
#include<stdio.h>
void menu()
{printf("************************\n");printf("**** 1.Add 2.Sub *******\n");printf("**** 3.Mul 4.Div *******\n");printf("**** 0.exit *******\n");printf("************************\n");
}
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int input = 0;int (*arr[5])(int , int ) = { NULL,Add,Sub,Mul,Div };int x = 0;int y = 0;int ret = 0;do{menu();printf("请选择:");scanf("%d", &input);if (input == 0){printf("退出计算器\n");break;}else if (input >= 1 && input <= 4){printf("请输入两个操作数:");scanf("%d %d", &x, &y);ret = arr[input](x, y);printf("%d\n", ret);}else{printf("选择错误,请重新选择\n");}} while (input);return 0;
}
相关文章:
详解指针(进阶版)(1)
前言:总篇章分为(1)和(2),本篇内容包括:指针数组,数组指针,&数组名与数组名的区分 数组传参 ,函数指针,函数指针数组 part 1:指…...
【OJ】盐荒子孙
📚Description: 盐体图 盐是对人类生存具有重要意义的物质之一。当中国古人从肉食为主转向谷食为主的时候,吃盐的需求就发生了,因为动物血肉里面包含有足够人体所需的盐分,而谷 物本身不包含盐分。在长达几十万年的旧石器时代&…...
Java数据结构 —— 手写线性结构(稀疏数组、栈、队列、链表)
目录 稀疏数组 顺序表 链表 单向顺序链表 双向链表 双向循环链表求解约瑟夫环(Joseph) 栈 顺序栈 队列 顺序队列 顺序循环队列 稀疏数组 当一个数组中大部分值为0,或者相同时,可以采用稀疏数组的方式来保存,从而节约存储…...
docker部署gitlab过程中遇到的一些问题记录
文章目录用nginx代理docker部署的gitlab服务密码重置docker0网卡异常离线安装apt的包用nginx代理docker部署的gitlab服务 一般咱们不会去暴露很多端口给外面,所以部署完gitlab后,我希望能够用nginx来代理我们的gitlab服务。 gitlab的docker部署参考这个…...
数组的定义与使用
文章目录 数组的基本概念数组的基本用法数组与方法互操作一、数组的基本概念 数组:可以看成是相同类型元素的一个集合。在内存中是一段连续的空间。 注意:1. 数组中存放的元素其类型相同 2. 数组的空间是连在一起的 3. 每个空间有自己的编号࿰…...
SAP ABAP用程序删除开发KEY
在BASISI系统管理中,用户的开发Key存储在DEVACCESS表中,如果由于审计需要删除一些用户的开发Key,而系统有限制SM30, SE16 or SE16N 等事务码的使用,你就可以通过一个小程序去删除开发Key。 代码如下: REPORT ZBCDEV…...
安卓设备TF卡概率性无法识别问题
现象 使用t卡的设备出货前检测是正常的,放在仓库中或出货后再开机,有概率的机器无法识别,重新插拔或重启无效,拔下来放pc电脑上识别后再插回设备则恢复正常能识别。 设备信息 系统: Android 8.1.0 数量:抽检有12%的设备无法识别 TF卡:SanDisk Ultra 64GB 10 A1 microS…...
linux安装nodejs和微信小程序自动化部署操作
一.运行环境安装 Node.js 并且版本大于 8.0基础库版本为 2.7.3 及以上开发者工具版本为 1.02.1907232 及以上安装node.js(1).下载node包官网地址:https://nodejs.org/en/download/如果英文不好的,可以看中文网站:https://nodejs.org/zh-cn/download/点击上面的进行下载,当然,也…...
JavaScript高级 Proxy Reflect
1. Proxy 1. 监听对象的变化 有一个对象,我们希望监听这个对象中的属性被设置或获取的过程 我们可以通过 Object.defineProperty 来实现 const obj {name: "why",age: 18,height: 1.88 }// 需求: 监听对象属性的所有操作 // 监听属性的操作 // 1.针对…...
Eth-trunk :LACP模式链路聚合实战
Eth-trunk : LACP模式链路聚合实战 需求描述 PC1和PC3数据vlan10 ,网段为192.168.10.0 /24PC2和PC4数据vlan20 ,网段为192.168.20.0 /24确保设备之间互联互通,使用最大互联带宽并没有环路确保相同网段的PC可以互通判断交换机之间的每个端口…...
【第二章 - 线性表之顺序表】- 数据结构(八千字详解)
目录 一、线性表的定义和特点 二、线性表的顺序表示和实现 2.1 - 线性表的顺序存储表示 2.2 - 顺序表中基本操作的实现 三、练习 3.1 - 移除元素 3.2 - 删除有序数组中的重复项 3.3 - BC100 有序序列合并 3.4 - 88.合并两个有序数组 四、顺序表的问题及思考 线性表、…...
【史上最全面esp32教程】RGB彩灯篇
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录rgb彩灯的介绍使用方法连线库操作彩灯变换颜色实验彩灯呼吸灯效果总结提示:以下是本篇文章正文内容,下面案例可供参考 rgb彩灯的介绍 ESP32…...
大规模 IoT 边缘容器集群管理的几种架构-5-总结
前文回顾 大规模 IoT 边缘容器集群管理的几种架构-0-边缘容器及架构简介大规模 IoT 边缘容器集群管理的几种架构-1-RancherK3s大规模 IoT 边缘容器集群管理的几种架构-2-HashiCorp 解决方案 Nomad大规模 IoT 边缘容器集群管理的几种架构-3-Portainer大规模 IoT 边缘容器集群管…...
逆风翻盘拿下感知实习offer,机会总是留给有准备的人
个人背景211本,985硕,本科是计算机科学与技术专业,研究生是自学计算机视觉方向,本科主要做C和python程序设计开发,java安卓开发,研究生主要做目标检测,现在在入门目标跟踪和3d目标检测。无论文&…...
SpringBoot整合阿里云OSS文件上传、下载、查看、删除
SpringBoot整合阿里云OSS文件上传、下载、查看、删除1、开发准备1.1 前置知识1.2 环境参数1.3 你能学到什么2. 使用阿里云OSS2.1 创建Bucket2.2 管理文件2.3 阿里云OSS文档3. 项目初始化3.1 创建SpringBoot项目3.2 Maven依赖3.3 安装lombok插件4. 后端服务编写4.1 阿里云OSS配置…...
对话数字化经营新模式:第2届22客户节(22Day)年猪宴圆满结束!
2023年2月22日,由杭州电子商务研究院联合贰贰网络(集团)、TO B总监联盟等发起举办的“第二届客户节22Day”暨2022年度爱名奖 AM AWARDS颁奖及22年猪宴沙龙活动圆满结束。 (主持人:杜灵芝) 本次沙龙邀请到浙江工业大学管理学院程志…...
数据结构——第二章 线性表(5)——双向循环链表
双向循环链表1.双向循环链表的定义2.双向循环链表的基本操作实现2.1 双向循环链表的初始化操作2.2.双向循环链表的插入操作2.3. 双向循环链表的删除操作1.双向循环链表的定义 单向链表便于查询后继结点,不便于查询前驱结点。为了方便两个方向的查询,可以…...
4面美团软件测试工程师,却忽略了这一点,直接让我前功尽弃
说一下我面试别人时候的思路 反过来理解,就是面试时候应该注意哪些东西;用加粗部分标注了 一般面试分为这么几个部分: 一、自我介绍 这部分一般人喜欢讲很多,其实没必要。大约5分钟内说清楚自己的职业经历,自己的核…...
robot remote server用这个server去远程获取ip
server端配置: 1、安装python环境 2、下载robot remote server 下载地址:https://pypi.python.org/pypi/robotremoteserver/(不要用pip下载,把robotremoteserver.py文件下载下来) 3、首先创建一个目录E:\rfremote\ &a…...
【WSL】Windows 上安装并启动
一、什么是 WSL Windows Subsystem for Linux 适用于 Linux 的 Windows 子系统 可以帮助我们自然、方便地在 Windows 上使用 Linux 子系统 二、安装 我们要安装的是 WSL2 , 因为其功能相对来说更加完善 1. 简化安装 — 本人亲测不好用 简化安装:高…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果 三、匿名函数与闭包1. 匿名函数(Lambda函…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
