用数组名作函数参数的详解,以及形参实参采用数组名,形参实参采用指针变量的几种情况解析
关于地址,指针,指针变量可以参考我的这篇文章:
地址,指针,指针变量是什么?他们的区别?符号(*)在不同位置的解释?_juechen333的博客-CSDN博客
https://blog.csdn.net/qq_57342311/article/details/129225045
目录
一、引入
1.1实例
1.2解释
1.3变量名和数组名作函数参数的比较
二、程序举例
2.1引入
三、总结
3.1归纳
3.2用指针变量作实参、形参举例
3.3用指针变量作实参,数组名作形参举例
一、引入
1.1实例
#include<stdio.h>
int main()
{void fun(int arr[], int n); //对fun函数进行声明int array[10]; //定义array数组... //一系列操作fun(array, 10); //用数组名作函数参数... //一系列操作return 0;
}void fun(int arr[], int n) //定义fun函数
{... //一系列操作
}
array 是实参数组名,arr 为形参数组名,当用数组名作参数时,如果形参数组中各元素的值发生变化,实参数组元素的值随之变化。这究竟为什么呢?请继续往下看。
1.2解释
(1)先看数组元素作实参时的情况
如果已定义一个函数
void swap(int x, int y);
假设函数的作用是将两个形参( x , y )的值交换,进行函数调用
swap (a[1],a[2]);
用数组元素 a[1] 和 a[2] 作实参的情况,与用变量作实参时一样,是 “值传递” 方式,将 a[1] 和 a[2] 的值单向传递给 x 和 y 。当 x 和 y 的值改变时,a[1] 和 a[2] 的值并不改变。
(2)再看用数组名作函数参数的情况
实参数组名代表该数组首元素的地址,而形参是用来接收从实参传递过来的数组首元素地址的。因此,形参应该是一个指针变量(只有指针变量才能存放地址)。实际上,C编译都是将形参数组名作为指针变量来处理的。例如:
fun(int arr[],int n);
但在程序编译时是将 arr 按指针变量处理的,相当于将函数 fun 的首部写成
fun(int* arr,int n);
以上两种写法是等价的。在该函数被调用时,系统会在 fun 函数中建立一个指针变量 arr,用来存放从主调函数传递过来的实参数组首元素的地址。如果在fun函数中用运算符 sizeof 测定 arr 所占的字节数,可以发现 sizeof(arr) 的值为 4 (用 VisualC++ 时)。这就证明了系统是把 arr 作为指针变量来处理的(指针变量在 Visual C++ 中占4个字节)。

当 arr 接收了实参数组的首元素地址后,arr 就指向实参数组首元素,也就是指向 array[0]。因此,*arr 就是 array[0]。arr+1 指向 array[1],arr+ 2 指向 array[2],arr+3 指向 array[3]。也就是说,*(arr+1),*(arr+2), *(arr+3) 分别是 array[1],array[2],array[3]。
根据前面介绍过的知识,*(arr+i) 和 arr[i] 是无条件等价的。
因此,在调用函数期间,arr[0] 和 *arr 以及 array[0] 都代表数组 array 序号为 0 的元素,依此类推,arr[3],*(arr+ 3),array[3] 都代表 array 数组序号为 3 的元素。
1.3变量名和数组名作函数参数的比较
| 实参类型 | 要求的形参类型 | 传递的信息 | 能否改变实参的值 |
| 变量名 | 变量名 | 变量的值 | 不能 |
| 数组名 | 数组名或指针变量 | 实参数组首元素的地址 | 能 |
说明: C 语言调用函数时虚实结合的方法都是采用 “值传递” 方式,当用变量名作为函数参数时传递的是变量的值,当用数组名作为函数参数时,由于数组名代表的是数组首元素地址,因此传递的值是地址,所以要求形参为指针变量。
在用数组名作为函数实参时,既然实际上相应的形参是指针变量,为什么还允许使用形参数组的形式呢?这是因为在 C 语言中用下标法和指针法都可以访问一个数组(如果有一个数组 a,则 a[i] 和 *(a+i) 无条件等价),用下标法表示比较直观,便于理解。因此许多人愿意用数组名作形参,以便与实参数组对应。从应用的角度看,用户可以认为有一个形参数组,它从实参数组那里得到起始地址,因此形参数组与实参数组共占同一段内存单元,在调用函数期间,如果改变了形参数组的值,也就是改变了实参数组的值。在主调函数中就可以利用这些已改变的值。
注意:实参数组名代表一个固定的地址,或者说是指针常量,但形参数组名并不是一个固定的地址,而是按指针变量处理。
二、程序举例
2.1引入
将数组 a 中 n 个整数按相反顺序存放,实参用数组名 a,形参可用数组名,也可用指针变量名。
(1)形参用数组名
#include<stdio.h>
int main()
{void inv(int x[], int n); //函数声明int a[10] = { 1,2,3,4,5,6,7,8,9,10 };for (int i = 0; i < 10; i++) //输出未交换时数组各元素的值{printf("%d ", a[i]);}printf("\n");inv(a, 10); //调用函数for (int i = 0; i < 10; i++) //输出交换后数组各元素的值{printf("%d ", a[i]);}
}void inv(int x[], int n) //形参x是数组名
{int temp;for (int i = 0; i < (n - 1) / 2; i++){int j = n - 1 - i;temp = x[i];x[i] = x[j];x[j] = temp;}
}
运行结果:

分析:
程序分析:在main函数中定义整型数组 a,并赋予初值。函数 inv 的形参数组名为 x。在定义 inv 函数时,可以不指定形参数组 x 的大小(元素的个数)。因为形参数组名实际上是一个指针变量,并不是真正地开辟一个数组空间(定义实参数组时必须指定数组大小,因为要开辟相应的存储空间)。inv 函数的形参 n 用来接收需要处理的元素的个数。在 main 函数中有函数调用语句 “inv(a,10);",表示要求对 a 数组的 10 个元素实行题目要求的颠倒排列。如果改为 “inv(a,5);",则表示要求将 a 数组的前 5 个元素实行颠倒排列,此时,函数 inv 只处理5个数组元素。
(2)形参用指针变量名
#include<stdio.h>
int main()
{void inv(int* x, int n); //函数声明int a[10] = { 1,2,3,4,5,6,7,8,9,10 };for (int i = 0; i < 10; i++) //输出未交换时数组各元素的值{printf("%d ", a[i]);}printf("\n");inv(a, 10); //调用函数for (int i = 0; i < 10; i++) //输出交换后数组各元素的值{printf("%d ", a[i]);}
}void inv(int* x, int n) //形参x是指针变量
{int temp;int* i = x;int* j = x + n - 1;for (; i < x + (n - 1) / 2; i++, j--){temp = *i;*i = *j;*j = temp;}
}
运行结果:

三、总结
3.1归纳
如果有一个实参数组,要想在函数中改变此数组中的元素的值,实参与形参的对应关系有以下 4 种情况。
(1)实参和形参都用数组名
int main()
{void f(int x[], int n);int a[10];...f(a, 10); //实参用数组名...
}void f(int x[], int n) //形参用数组名
{...
}
(2)实参用数组名,形参用指针变量
int main()
{void f(int* x, int n);int a[10];...f(a, 10); //实参用数组名...
}void f(int* x, int n) //形参用指针变量
{...
}
(3)实参和形参都用指针变量
int main()
{void f(int* x, int n);int a[10];int* p = a;...f(p, 10); //实参用指针变量...
}void f(int* x, int n) //形参用指针变量
{...
}
(4)实参用指针变量,形参用数组名
int main()
{void f(int x[], int n);int a[10];int* p = a;...f(p, 10); //实参用指针变量...
}void f(int x[], int n) //形参用数组名
{...
}
3.2用指针变量作实参、形参举例
改写(二)中的实例
#include<stdio.h>
int main()
{void inv(int* x, int n); //函数声明int a[10] = { 1,2,3,4,5,6,7,8,9,10 };int* p = a;for (int i = 0; i < 10; i++) //输出未交换时数组各元素的值{printf("%d ", a[i]);}printf("\n");inv(p, 10); //调用函数for (int i = 0; i < 10; i++) //输出交换后数组各元素的值{printf("%d ", a[i]);}
}void inv(int* x, int n) //形参x是指针变量
{int temp;int* i = x;int* j = x + n - 1;for (; i < x + (n - 1) / 2; i++, j--){temp = *i;*i = *j;*j = temp;}
}
运行结果:

3.3用指针变量作实参,数组名作形参举例
对数组 a[10] 由大到小进行排序,采用选择排序的算法
#include<stdio.h>
int main()
{void sort(int x[], int n); //函数声明int a[10] = { 1,3,5,7,9,2,4,6,8,10 };int* p = a;for (int i = 0; i < 10; i++) //输出未交换时数组各元素的值{printf("%d ", a[i]);}printf("\n");sort(p, 10); //调用函数for (int i = 0; i < 10; i++) //输出交换后数组各元素的值{printf("%d ", a[i]);}
}void sort(int x[], int n)
{for (int i = 0; i < n - 1; i++) //i的取值范围[0,n-1){int max_idx = i; //记录最大数值所在位置for (int j = i + 1; j < n; j++) //j的取值范围[1,n){if (x[j] > x[max_idx]) { max_idx = j; } //更新最大值所在位置}if (max_idx != i) //进行交换{int temp;temp = x[i];x[i] = x[max_idx];x[max_idx] = temp;}}
}
运行结果:

上面 sort 函数中是用数组名作为形参,也可以用指针变量作为形参
void sort(int* x, int n)
{for (int i = 0; i < n - 1; i++) //i的取值范围[0,n-1){int max_idx = i; //记录最大数值所在位置for (int j = i + 1; j < n; j++) //j的取值范围[1,n){if (*(x + j) > *(x + max_idx)) { max_idx = j; } //更新最大值所在位置}if (max_idx != i) //进行交换{int temp;temp = *(x + i);*(x + i) = *(x + max_idx);*(x + max_idx) = temp;}}
}相关文章:
用数组名作函数参数的详解,以及形参实参采用数组名,形参实参采用指针变量的几种情况解析
关于地址,指针,指针变量可以参考我的这篇文章: 地址,指针,指针变量是什么?他们的区别?符号(*)在不同位置的解释?_juechen333的博客-CSDN博客https://blog.csd…...
k8s中的PV和PVS
前言:容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)…...
【云原生】Gateway网关选型
网关一般分为流量网关和业务网关,流量网关负责接入所有的流量,并分发给不同的子系统,那在具体的业务接入之前,还有一层业务网关。流量网关提供全局性的、与后端业务应用无关的策略,例如 HTTPS证书卸载、Web防火墙、全局…...
QML Button详解
1.Button简介 Button表示用户可以按下或单击的按钮控件。按钮通常用于执行一个动作,或回答一个问题。典型的按钮有确定、应用、取消、关闭、是、否和帮助。 Button继承自AbstractButton,提供了以下几种信号。 void canceled() //当按…...
【编程实践】什么是好/坏代码?非程序员的示例
What is good/bad code? An illustrated example for non-programmers 什么是好/坏代码?非程序员的示例 目录 What is good/bad code? An illustrated example for non-programmers什么是好/坏代码?非程序员的示例 So what is ‘Bad Code’, as a layperson?那么,作为…...
一个简单的Sublime设置
问题 如果读者熟悉我,应该会发现我经常使用 VSCode 作为主力编辑器,但随着我安装的 VSCode 的插件逐渐增加,我发现对于部分较小的任务使用 VSCode 过于笨重,比如简单的 Markdown 文件编辑工作。 在经过一系列寻找后,…...
c语言经典例题-选择结构程序设计进阶
(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 快递费用计算: 题目: 代码思路: 代码表示: 计算一元二…...
NOI 2023春季测试 游记
怎么说,没遇到大波折即幸运。 Day 0 睡到下午三点,然后列了一堆复习计划,大概是左偏树等一些早就忘没的科技。 但是沉迷打块,最后基本什么计划也没完成。 白天睡多了,晚上睡不着,大概半梦半醒过了一整夜…...
【VC 7/8】vCenter Server 基于文件的备份和还原Ⅱ——使用 FTP 协议备份 VC(VAMI 英文)
目录2. 备份 vCenter Server2.1 使用 FTP 协议备份 VC(1)登录 vCenter Server 管理界面(2)进入Backup页面(3)配置 Backup Schedule(4)开始备份(5)备份成功&am…...
Python基础—文件操作(二)
Python基础—文件操作(二) CSV格式文件 逗号分隔值,以纯文本形式存储表格数据 由任意数目的记录组成,记录间以换行符分隔 每条记录由字段组成,字段间用逗号或制表符分隔 每条记录都有同样的字段序列 如有列名,位于文件第一行 每条…...
学校的班级个数【并查集基础应用,Java实现】
题目描述 现有一个学校,学校中有若干个班级,每个班级中有若干个学生,每个学生只会存在于一个班级中。如果学生A和学生B处于一个班级,学生B和学生C处于一个班级,那么我们称学生A和学生C也处于一个班级。 现已知学校中共…...
WSL2使用Nvidia-Docker实现CUDA版本自由切换
众所周知,深度学习的环境往往非常麻烦,经常不同的项目所依赖的 torch、tensorflow 包对 CUDA 的版本也有不同的要求,Linux 下进行 CUDA 的管理比较麻烦,是一个比较头疼的问题。 随着 WSL2 对物理机显卡的支持,Nvidia-…...
pygame9 扫雷游戏2
一、响应鼠标左键事件 pygame.MOUSEBUTTONDOWN 表示鼠标事件发生, pygame.mouse.get_pressed()[0] 确认是鼠标左键被按下 pygame.mouse.get_pos() 获取到鼠标按下时的坐标值。 因此,我们可以在事件逻辑中例用此三个函数判断鼠标事件及对应的坐标&#x…...
逻辑电路代数运算(上)
逻辑代数L是一个封闭的代数系统,由一个逻辑变量集K,常量0和1,以及与或非三种基本运算构成。 参与逻辑运算的变量叫逻辑变量,用字母A,B……表示。每个变量的取值非0 即1。 0、1不表示数的大小,而是代表两种不…...
Rabbit快速入门
入门案例 需求:使用简单模式完成消息传递 步骤: 创建工程(生成者、消费者) 分别添加依赖 编写生产者发送消息 编写消费者接收消息 3.1.2. 添加依赖 往heima-rabbitmq的pom.xml文件中添加如下依赖: <dependenc…...
【react+ts- forwardRef】
reactts- forwardRef1. 学习资料2. 普通input透传2.1 TS版本2.2 JS版本3. TS-Antd-Form组价透传引用传递(Ref forwading)是一种通过组件向子组件自动传递 引用ref 的技术。对于应用者的大多数组件来说没什么作用。但是对于有些重复使用的组件,…...
计算机网络-- 网络层(day06)
文章目录网络层思维导图IPv4地址的应用规划定长的子网掩码变长的子网掩码VLSMIP数据报的发送和转发过程主机发送IP数据报路由器转发IP数据报静态路由选择动态路由选择路由选择协议概述常见的路由选择协议路由器的基本结构路由信息协议RIP的基本工作原理开放最短路径优先OSPF的基…...
docker 镜像
一、介绍 镜像:是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码,运行时需要的库,环境变量和配置文件等)这个打包好的运行环境就是image镜像文件。 只有通过这个镜…...
JUC并发编程与源码分析笔记11-Java对象内存布局和对象头
先从阿里及其它大厂面试题说起 你觉得目前面试,你还有那些方面理解的比较好,我没问到的,我说了juc和jvm以及同步锁机制那先说juc吧,说下aqs的大致流程cas自旋锁,是获取不到锁就一直自旋吗?cas和synchronized区别在哪…...
JavaSE之集合篇
文章目录前言一、集合概述集合继承结构图二、Collection接口中常用方法2.1Collection中存放什么元素?2.2常用方法2.3迭代器三、List接口中常用的方法四、ArrayList初始化容量及扩容五、Vector六、Map接口常用方法七、Properties前言 由于在刷题过程中,经…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
TJCTF 2025
还以为是天津的。这个比较容易,虽然绕了点弯,可还是把CP AK了,不过我会的别人也会,还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...
