【C语言】数组名作函数参数

news/2024/11/26 7:21:07/

数组名作函数参数

    • 引例
    • 思考
    • 例2
    • 通用性
    • 指针形参和数组形参
    • 几点说明

引例

主函数中输入10个整数,并存入一个一维数组中;然后在被调函数中,将0号元素的值``改为原值的10倍;最后在主函数中输出结果。
思路
若想在被调函数中,对主调函数中某个局部变量的值进行修改,则必须将该局部变量的地址传递到被调函数中,然后以跨函数间接引用的形式进行赋值。
代码实现

#include<stdio.h>
void fun (int *p);
int main(void)
{int a[10],i;for (i=0;i<10;i++)scanf("%d",&a[i]);fun(&a[0]);for (i=0;i<=9;i++)printf("%d",a[i]);return 0;
}
void fun(int *p)
{*p=*p*10;return 0;
}

执行过程分析
首先,程序的执行控制权在主函数,在主函数中,定义一维数组,整型变量i,然后完成对整型数组的赋值。当函数执行到:

fun(&a[0]);

此时,调用被调函数fun(),此时实参&a[0],传递给形参,也就是在将a[0]的地址传递给形参p
参数传递之后,程序的执行控制权交给了被调函数fun(),参数传递完成之后,就形成了如下这样的指向关系:
在这里插入图片描述
然后此时通过间接引用可以修改a[0]的值。
但是注意,不可以直接以以下这种方式直接引用

a[0]=a[0]*10;

因为a[0]是局部变量,只可以在主函数中使用。
之后,被调函数执行到return,返回到主调函数,此时函数的执行控制权交给了主函数。在主函数中,再完成一维数组元素的全部输出。

思考

那么,如果要在被调函数中对主调函数中的一维数组的所有元素进行间接引用,是不是需要将每个元素的地址都传递到被调函数中呢?
实际上,并不需要。这是因为数组中元素的地址是连续有序的,只要知道数组中0号元素的地址,就可以求得其他元素的地址。
因此,只需要将数组的首地址传递到被调函数中即可。`

例2

在主函数中,输入10个整数,并存入一个一维数组a中,然后在被调函数中,将所有数组元素的值修改为原来的10倍;最后在主函数中输出结果。
思路
1.在主函数中以数组名a作为实参。
2.在被调函数中以指针变量p作为形参。
3.那么,参数传递之后,在被调函数中就可以用指针变量p来间接引用主调函数中的数组元素了。
数组在内存中的地址是连续的,就可以知道其他元素的地址
我们知道a[0]的地址为p,依次我们可以知道a[1]的地址为p+1,a[2]的地址为p+2…a[i]的地址为p+i。
此时形成这样的指向关系:
在这里插入图片描述
代码实现

#include<stdio.h>
void fun (int *p);
int main(void)
{int a[10],i;for (i=0;i<10;i++)scanf("%d",&a[i]);fun(a);for (i=0;i<=9;i++)printf("%d ",a[i]);return 0;
}
void fun(int *p)
{int i;for (i=0;i<10;i++)*(p+i)=*(p+i)*10; //间接引用 *(p+i)即a[i]return ;
}

*(p+i)即a[i]的间接引用形式。

通用性

由于数组名只是一个地址,并未包含数组的长度信息,因此为了提高被调函数通用性,通常需要设置另外一个参数,专门用来传递数组的长度
改进之后:

#include<stdio.h>
void fun (int *p,int n);
int main(void)
{int a[10],i;for (i=0;i<10;i++)scanf("%d",&a[i]);fun(a,10);for (i=0;i<=9;i++)printf("%d ",a[i]);return 0;
}
void fun(int *p,int n)
{int i;for (i=0;i<n;i++)*(p+i)=*(p+i)*10;return ;
}

原来的被调函数只能针对只有十个元素的数组进行修改,而上面修改过的被调函数可以针对具有n个元素的元素进行修改。因此,具有更好的通用性
可以发现,用数组名作函数参数时,只需要向被调函数传递数组的首地址长度而不需要传递所有数组元素的值,因而具有较高的存储效率时间效率

指针形参和数组形参

尽管形参p指针变量,而不是数组名,然后为了提高程序的直观性,C语言允许将间接引用形式的*(p+i)表示为数组元素形式的p[i]
在这里插入图片描述
从而可以将被调函数改写为下面的形式:

void fun(int *p,int n)
{int i;for (i=0;i<n;i++)p[i]=p[i]*10;return ;
}

甚至于函数头的指针形参,也可以改写成数组形式,从而进一步将被调函数进一步改写为

void fun(int p[],int n) //*p改写为p[]
{int i;for (i=0;i<n;i++)p[i]=p[i]*10;return ;
}

从而改进之后完整的源程序:

#include<stdio.h>
void fun (int *p,int n);
int main(void)
{int a[10],i;for (i=0;i<10;i++)scanf("%d",&a[i]);fun(a,10);for (i=0;i<=9;i++)printf("%d ",a[i]);return 0;
}
void fun(int p[],int n)
{int i;for (i=0;i<n;i++)p[i]=p[i]*10;return ;
}

几点说明

1.将函数头中的指针形参改写为数组形式,只是为了直观。
本质上来说,数组形参仍然是指针变量,因此不必在当括号中指定数组形参的长度。
例如:

void fun(int p[],int n)

2.在被调函数函数头中定义的数组可以称之为形参数组。在本质上形参数组实参数组同一个数组。
在这里插入图片描述
这是因为形参数组的元素p[i],等同于*(p+i),而 * (p+i)即p[i],又是实参数组元素a[i]间接引用形式;从而p[i]表示的数组元素就是a[i]


http://www.ppmy.cn/news/85372.html

相关文章

【Linux】线程同步/生产消费模型/线程池/读写锁

目录 1.Linux线程同步 1.1.条件变量 1.1.1.同步概念与竞态条件 1.1.2.条件变量函数 初始化和销毁 1.1.3.等待条件满足 1.1.5.为什么 pthread_cond_wait 需要互斥量? 1.1.6.条件变量使用规范 2.生产者消费者模型 2.1.模型概念 2.2.模型优点 2.3.基于Blocking Queue的…

MySQL---事务

1. 事务操作 开启事务&#xff1a;Start Transaction 任何一条DML语句(insert、update、delete)执行&#xff0c; 标志事务的开启命令&#xff1a;BEGIN 或 START TRANSACTION 提交事务&#xff1a;Commit Transaction 成功的结束&#xff0c;将所有的DML语句操作历史记录…

小电流接地系统单相接地故障选线及保护

小电流接地系统单相接地故障选线及保护 姓名[1] 【摘要】&#xff1a;小电流系统单相接地故障选线以及定位一直是研究的热点&#xff0c;本文基于小电流系统出现单相接地短路后的特征&#xff0c;提出利用稳态特征和暂态特征信息结合的方式进行故障选线与保护&#xff0c;然后利…

【数据结构】线性表之栈、队列

前言 前面两篇文章讲述了关于线性表中的顺序表与链表&#xff0c;这篇文章继续讲述线性表中的栈和队列。 这里讲述的两种线性表与前面的线性表不同&#xff0c;只允许在一端入数据&#xff0c;一段出数据&#xff0c;详细内容请看下面的文章。 顺序表与链表两篇文章的链接&…

Selenium2023最全攻略(元素操作,浏览器操作等)附完整代码!

一、元素操作方法 方法&#xff1a; 1、.send_keys() # 输入方法 2、.click() # 点击方法 3、.clear() # 清空方法 注意&#xff1a;在输入方法之前一定要清空操作!! # 导包 from time import sleep from selenium import webdriver # 实例化浏览器 driver webdriver.Chrome(…

Tomcat源码:Acceptor与Poller、PollerEvent

参考资料&#xff1a; 《Tomcat源码解析系列&#xff08;十一&#xff09;ProtocolHandler》 《Tomcat源码解析系列&#xff08;十二&#xff09;NioEndpoint》 前文&#xff1a; 《Tomcat源码&#xff1a;启动类Bootstrap与Catalina的加载》 《Tomcat源码&#xff1a;容器…

day2 嵌入式数据库之sqlite3(下)

目录 打开数据库 关闭数据库 得到错误信息的描述 API函数 回调函数 查询回调函数 不使用回调函数查询 简易学生表创建 打开数据库 int sqlite3_open(const char *filename, /* Database filename (UTF-8) */sqlite3 **ppDb /* OUT: SQLite db handle */); 参…

React Hooks useRef 源码解读+最佳实践

参考&#xff1a;https://juejin.cn/post/7027949526170206239 入口 下篇文章有入口源码详解&#xff0c;想看的可以跳转过去&#xff0c;这里就不放源码了&#xff0c;简单梳理一下流程吧 React Hooks useState 使用详解实现原理源码分析 流程 beginWork 判断组件类型&#x…