C:数组传参的本质
1、一维数组传参的本质
数组传参是指在函数调用时将数组作为参数传递给函数。
int main() {int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };test(arr);return 0;}
数组传参只需要写数组名就可以了。注意:数组名是arr,而不是arr[10]
数组传参形参该怎么写呢?
void test(int arr[])//元素个数写不写无所谓
等下会说为什么写不写都不影响
现在我们来分别在(test)函数外部与函数内部计算数组元素的个数、
来,展示!
可以看到在函数内部sz2结果为1,而函数外部sz1结果为10;这是为什么呢?
关于sz1 = 10;的结果我们都清楚,sizeof(arr)求得数组的总大小,sizeof(arr[0])求得数组首元素的大小,然后得出元素个数,但是为什么在test函数内部求得的元素个数结果变为1了呢?
我们来逆推一下,首先sizeof(arr[0])表示的是数组首元素的大小是不变的,因此sizeof(arr[0])等于4
sz2 = sizeof(arr) / 4 = 1;因此sizeof(arr)也等于4,那么在什么情况下能得到aizeof(arr) = 4 呢?
在数组传参的时候 test(arr);我们传递的是整个数组吗?还记得前面关于数组名的理解吗?这里arr既不是在sizeof中,前面也没有&符号,所以,test(arr)中的arr指的就是数组首元素的大小,因此我们传参过去的是首元素的地址,这便是一维数组传参的本质,既如此,我们便可以明白aizeof(arr) = 4是怎么得到的了,地址在32位机器上占4个字节,在64位机器上占8个字节 ,小编是在32位上操作的,所以最终得到izeof(arr) = 4 的结果。
void test(int arr[])//元素个数写不写无所谓
{int sz2 = sizeof(arr) / sizeof(arr[0]);printf("sz2 = %d\n", sz2);
}
#include <stdio.h>
int main() {int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz1 = sizeof(arr) / sizeof(arr[0]);printf("sz1 = %d\n", sz1);test(arr);return 0;}
综上:数组传参传递的就是首元素地址
1.我们传递的不是整个数组,函数形参的部分是不会真实创建数组的,所以就不需要数组大小,也就是形参部分元素大小写不写都无所谓,没有什么影响
2.数组传过去的是数组首元素地址,地址应该拿指针来接收,所以函数形参部分应该使用指针变量来接收,而我们写成int arr[])是为了更加方便我们的理解。
void test(int arr[])可以写为void test(int* arr)
注意:
一维数组传参的时候,形参可以写成数组的方式,主要是为了方便理解,形参也可以写成指针变量的方式
如果我们想要在函数内部获取数组元素的个数,该怎么写呢?
void test(int arr[10],int sz)
{//遍历数组int i = 0;for (i = 0; i < sz; i++){printf(" %d ", arr[i]);}
}
#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(arr) / sizeof(arr[0]);test(arr,sz);return 0;
}
2、二维数组传参的本质
理解二维数组传参的本质
二维数组传参本质上也是传递了地址,传递的是第一行这个一维数组的地址。
我们先来看一个二维数组传参的代码:
#include <stdio.h>
#include <string.h>
void print(int arr[3][5],int a,int b)
{for (int i = 0; i < a; i++) //遍历行数{for (int j = 0; j < b; 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, };print(arr, 3, 5);return 0;
}
上列代码中实参是⼆维数组,形参也写成⼆维数组的形式,那我们该怎么理解二维数组传参的操作呢?
从上图中,我们可以看到二维数组传参传递的也是数组名,数组名是什么呢?
数组名是数组首元素的地址,所以二维数组实参传递的是地址,既然传递的是地址,那么形参也就可以使用指针来接收。
这里你可能又会有一个疑问,二维数组的数组名到底是表示谁的地址?也就是二维数组的首元素是什么?
这里我们就需要对二维数组做一些更深入的理解了,前面关于数组的介绍篇章也说过
关于二维数组,我们可以把一维数组当作是数组的元素,那么这时候的数组就是二维数组
1 | 1 | 2 | 3 | 4 | 5 | 1 | 2 | 3 | 4 | 5 | |||
int | int | int | int | int | int | 2 | 3 | 4 | 5 | 6 | |||
3 | 4 | 5 | 6 | 7 | |||||||||
数组元素 | 一维数组 | int | int | int | int | int | |||||||
二维数组 |
所以我们可以这么理解:
二维数组其实是一维数组的数组,二维数组的每一个元素都是一维数组
这样我们就可以把二维数组的每一行看作是一个元素,所以二维数组的首元素就是它的第一行
二维数组的数组名表示的就是第一行的一维数组的地址。
也就是说我们二维数组实参传过去的就是一维数组的地址
形参部分如果想要写成指针的方式,该怎么写呢?
由于实参传递的是数组的地址,所以形参应该使用数组指针来接收
表达形式:int (*arr)[5],还记得为什么这么写吗?
arr与*结合说明arr是指针,指针指向的是数组 [5]说明数组有5个元素,每个元素类型是int
(*arr)是因为需要arr先于*结合。如果不使用圆括号,arr就不再是指针变量,而是会与[5]结合变为数组名。
C:指针学习-指针变量—学习笔记-CSDN博客
如果对于数组指针有一些不明白的地方,可以看一看这篇文章哟!
参部分用指针改写后:void print ( int(*arr)[5] , int a, int b)
二维数组在内存中是连续存放的,所以
1 2 3 4 5
2 3 4 5 6 可以理解为 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7
3 4 5 6 7
到这里是否能够理解二维数组传参的本质了吗?
二维数组传参传递的不是二维数组,而是二维数组首元素的地址,也就是第一行的地址,所以形参的部分要拿数组指针来接收。
使用指针访问到二维数组的全部元素
图片文字较小,还请见谅,当时画完后没注意到,抱歉抱歉!可以放大观看,如有不理解的地方,也可以私我,我们一起探讨!
代码就可以改写成这样:
void print(int(*arr)[5], int a, int b)
{for (int i = 0; i < a; i++){for (int j = 0; j < b; j++){printf("%d ", *(*(arr + i)+j));}printf("\n");}
}
是不是感觉这样写不是很好理解,还可以换一种方式写*(*(arr + i)+j)
*(*(arr + i)+j)也可以写成arr[i][j]
这两种一种是指针的方式,一种使用数组下标的方式。
3、总结:
数组传参传递的都是地址,所以形参都可以使用指针来接收
一位数组传参传递的是首元素地址,使用(类型)指针来接收,
二维数组传参传递的是一维数组的地址,使用数组指针来接收。
本篇文章到这里就结束了,希望能够对大家理解数组传参有所帮助!
相关文章:

C:数组传参的本质
1、一维数组传参的本质 数组传参是指在函数调用时将数组作为参数传递给函数。 int main() {int arr[10] { 1,2,3,4,5,6,7,8,9,10 };test(arr);return 0;}数组传参只需要写数组名就可以了。注意:数组名是arr,而不是arr[10] 数组传参形参该怎么写呢&am…...
excel 2019版本的index match搜索功能
{TEXTJOIN("", TRUE, IF((sheet2!A:A"文字")*(sheet2!C:CC5), sheet2!G:G, ""))} excel单元格输入公式后: TEXTJOIN("", TRUE, IF((sheet2!A:A"文字")*(sheet2!C:CC5), sheet2!G:G, "")) 按CtrlShi…...
【问题解决】apache.poi 3.1.4版本升级到 5.2.3,导出文件报错版本无法解析
【问题解决】apache.poi 3.1.4版本升级到 5.2.3,导出文件报错无法解析 3.1.4版本代码: /*** 创建workbook* param inp* return* throws Exception*/public Workbook createworkbook(InputStream inp) throws Exception {if (!inp.markSupported()) {inp…...

(亲测有效)SpringBoot项目集成腾讯云COS对象存储(2)
接上文(亲测有效)SpringBoot项目集成腾讯云COS对象存储(1)-CSDN博客 目录 3、通用能力类 文件下载 测试 3、通用能力类 文件下载 官方文档介绍了2种文件下载方式。一种是直接下载 COS 的文件到后端服务器(适合服务…...

界面优化 - QSS
目录 1、背景介绍 2、基本语法 3、QSS 设置方式 3.1 指定控件样式设置 代码示例: 子元素受到影响 3.2 全局样式设置 代码示例: 使用全局样式 代码示例: 样式的层叠特性 代码示例: 样式的优先级 3.3 从文件加载样式表 代码示例: 从文件加载全局样式 3.4 使用 Qt Desi…...
实现基于TCP协议的服务器与客户机间简单通信
服务器端程序 #include <myhead.h> #define SER_PORT 6666 //服务器端口号 #define SER_IP "192.168.2.53" //服务器ip地址 int main(int argc, char const *argv[]) { /*创建套接字 int socket(int domain, int type, int protocol);*/ …...
在uniapp中使用navigator.MediaDevices.getUserMedia()拍照并上传服务器
产品提了这样一个需求: 移动端拍照上传后图片不保存在用户设备上,试了好几种方法,uni-file-picker、uni.chooseImage、input type‘file’,安卓手机都会默认把图片保存在手机,于是各种查资料,找到了以下方法…...
PULLUP
重要提示:PULLUP属性已被弃用,应替换为PULLTYPE 财产。 PULLUP在三态输出或双向端口上应用弱逻辑高,以防止 它从漂浮。PULLUP属性保证逻辑高电平,以允许三态网络 以避免在不被驱动时漂浮。 输入缓冲器(如IBUFÿ…...

【无标题】乐天HIQ壁挂炉使用
这里写自定义目录标题 1.按键①: 按一下,小液晶显示的温度是所设定的供暖温度; 按二下,小液晶显示的温度是所设定的生活热水温度; 按三下,小液晶显示的温度是所设定的室内温度; 如果忘记按几下的…...

使用Python编写AI程序,让机器变得更智能
人工智能(AI)是当今科技领域最热门的话题之一。随着Python编程语言的逐渐流行,它已经成为许多人工智能编程的首选语言。本文将介绍如何使用Python编写AI程序,让机器变得更智能。 首先,Python提供了大量的AI库和工具&a…...

VScode + PlatformIO 和 Keil 开发 STM32
以前经常使用 KEIL 写 STM32 的代码,自从使用 VScode 写 ESP32 后感觉 KEIL 的开发环境不美观不智能了,后面学习了 VScode 开发 STM32 。 使用过程中发现 串口重定向在 KEIL 中可以用,搬到 VScode 后不能用,不用勾选 Use Micro LI…...

PostgreSQL 练习 ---- psql 新增连接参数
目标 添加一个连接参数,默认为 false 。当 psql 连接时,若该连接参数非 “true” 时,用户 “u1“ 对表对象无操作权限,包括自己拥有的表。 连接机制简介 连接过程如下所述: 客户端初始化一个空连接,设置…...

pdf翻译软件哪个好用?多语言轻松转
想知道怎么用pdf翻译器在线翻译吗?无需复杂操作,一键即可解锁语言障碍。 在这个全球化日益加深的时代,掌握pdf文件的快速翻译技巧尤为重要。 无论是学习、工作还是国际交流,以下4个免费pdf翻译技巧都将是你不可或缺的得力助手。…...

培训第三十天(ansible模块的使用)
上午 ansible是⼀种由Python开发的⾃动化运维⼯具,集合了众多运维⼯ 具(puppet、cfengine、chef、func、fabric)的优点,实现了批量 系统配置、批量程序部署、批量运⾏命令等功能。 1、学习ansible的使用 ansible 主机ip|域名|组…...

关于Log4net的使用记录——无法生成日志文件输出
关于Log4net的使用记录 前言遇到的问题具体使用总结前言 最近在使用log4net进行日志记录,保存一些需要的数据,以便后期使用需要。在使用的时候出现没有生成日志文件,针对这些问题,发现解决的办法! 遇到的问题 报错,提示没有找到对应的文件。 log4net:ERROR Failed to f…...
golang Kratos 概念
"Kratos"指的是一个开源的微服务框架,它用于构建高性能和可扩展的云原生应用。Kratos框架提供了一套丰富的工具和库,旨在简化微服务的开发和维护。下面是Kratos框架的一些基本概念: 服务构建与注册: gRPC与HTTP服务&…...

入门 MySQL 数据库:基础指南
简介 MySQL 是一个非常流行的开源关系型数据库管理系统(RDBMS),广泛用于 Web 应用、企业应用和数据仓库。本博客将引导你从零开始,学习 MySQL 数据库的基础知识。 什么是 MySQL? MySQL 是一个基于 SQL(Str…...

【Hexo系列】【3】使用GitHub自带的自定义域名解析
上一期我们通过学习【Hexo系列】【2】使用Vercel加速Hexo博客访问使用Vercel进行GitHub同步与加速,有时候Vercel也不太稳定访问不了。本身GitHub也是支持自定义域名的,本次教程将讲解如何使用GitHub自带的自定义域名解析。 1. GitHub设置 1.1 登录GitH…...

智能监控,无忧仓储:EasyCVR视频汇聚+AI智能分享技术为药品仓库安全保驾护航
随着科技的飞速发展,药品仓库的安全管理正迎来前所未有的变革。药品作为直接关系到公众健康的重要物资,其安全存储和监管显得尤为重要。在这个背景下,视频汇聚平台EasyCVR视频智能管理系统的应用,为药品仓库的安全监管提供了强有力…...

本地创建PyPI镜像
背景: 在安装一些库时,经常需要反复下载包(有的体积比较大,所以会比较慢),所以考虑在本地创建一个pypi镜像,把常用的库缓存下来,这样安装就会很省事.比较从本地安装库和从服务器下载会快很多. 安装使用 安装:pip install devpi 初始化: devpi-init --serverdirF:\pypioutput…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...