C语言指针变量作为函数参数

news2025/1/16 21:56:54

在C语言中,函数的参数不仅可以是整数、小数、字符等具体的数据,还可以是指向它们的指针。用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着函数的结束而被销毁。

像数组、字符串、动态分配的内存等都是一系列数据的集合,没有办法通过一个参数全部传入函数内部,只能传递它们的指针,在函数内部通过指针来影响这些数据集合。

有的时候,对于整数、小数、字符等基本类型数据的操作也必须要借助指针,一个典型的例子就是交换两个变量的值。

有些初学者可能会使用下面的方法来交换两个变量的值:

#include<stdio.h>

voidswap(int a,int b){
int temp;//临时变量
    temp = a;
    a = b;
    b = temp;
}

intmain(){
int a =66, b =99;
swap(a, b);
printf("a = %d, b = %d\n", a, b);
return0;
}

运行结果:

a = 66, b = 99

从结果可以看出,a、b 的值并没有发生改变,交换失败。这是因为 swap() 函数内部的 a、b 和 main() 函数内部的 a、b 是不同的变量,占用不同的内存,它们除了名字一样,没有其他任何关系,swap() 交换的是它内部 a、b 的值,不会影响它外部(main() 内部) a、b 的值。

改用指针变量作参数后就很容易解决上面的问题:

#include<stdio.h>

voidswap(int*p1,int*p2){
int temp;//临时变量
    temp =*p1;
*p1 =*p2;
*p2 = temp;
}

intmain(){
int a =66, b =99;
swap(&a,&b);
printf("a = %d, b = %d\n", a, b);
return0;
}

运行结果:

a = 99, b = 66

调用 swap() 函数时,将变量 a、b 的地址分别赋值给 p1、p2,这样 *p1、*p2 代表的就是变量 a、b 本身,交换 *p1、*p2 的值也就是交换 a、b 的值。函数运行结束后虽然会将 p1、p2 销毁,但它对外部 a、b 造成的影响是“持久化”的,不会随着函数的结束而“恢复原样”。

需要注意的是临时变量 temp,它的作用特别重要,因为执行*p1 = *p2;语句后 a 的值会被 b 的值覆盖,如果不先将 a 的值保存起来以后就找不到了。

这就好比拿来一瓶可乐和一瓶雪碧,要想把可乐倒进雪碧瓶、把雪碧倒进可乐瓶里面,就必须先找一个杯子,将两者之一先倒进杯子里面,再从杯子倒进瓶子里面。这里的杯子,就是一个“临时变量”,虽然只是倒倒手,但是也不可或缺。

用数组作函数参数

数组是一系列数据的集合,无法通过参数将它们一次性传递到函数内部,如果希望在函数内部操作数组,必须传递数组指针。下面的例子定义了一个函数 max(),用来查找数组中值最大的元素:

#include<stdio.h>

intmax(int*intArr,int len){
int i, maxValue = intArr[0];//假设第0个元素是最大值
for(i=1; i<len; i++){
if(maxValue < intArr[i]){
            maxValue = intArr[i];
}
}

return maxValue;
}

intmain(){
int nums[6], i;
int len =sizeof(nums)/sizeof(int);
//读取用户输入的数据并赋值给数组元素
for(i=0; i<len; i++){
scanf("%d", nums+i);
}
printf("Max value is %d!\n",max(nums, len));

return0;
}

运行结果:

12 55 30 8 93 27

Max value is 93!

参数 intArr 仅仅是一个数组指针,在函数内部无法通过这个指针获得数组长度,必须将数组长度作为函数参数传递到函数内部。数组 nums 的每个元素都是整数,scanf() 在读取用户输入的整数时,要求给出存储它的内存的地址,nums+i就是第 i 个数组元素的地址。

用数组做函数参数时,参数也能够以“真正”的数组形式给出。例如对于上面的 max() 函数,它的参数可以写成下面的形式:

intmax(int intArr[6],int len){
int i, maxValue = intArr[0];//假设第0个元素是最大值
for(i=1; i<len; i++){
if(maxValue < intArr[i]){
            maxValue = intArr[i];
}
}
return maxValue;
}

int intArr[6]好像定义了一个拥有 6 个元素的数组,调用 max() 时可以将数组的所有元素“一股脑”传递进来。

读者也可以省略数组长度,把形参简写为下面的形式:

intmax(int intArr[],int len){
int i, maxValue = intArr[0];//假设第0个元素是最大值
for(i=1; i<len; i++){
if(maxValue < intArr[i]){
            maxValue = intArr[i];
}
}
return maxValue;
}

int intArr[]虽然定义了一个数组,但没有指定数组长度,好像可以接受任意长度的数组。

实际上这两种形式的数组定义都是假象,不管是int intArr[6]还是int intArr[]都不会创建一个数组出来,编译器也不会为它们分配内存,实际的数组是不存在的,它们最终还是会转换为int *intArr这样的指针。这就意味着,两种形式都不能将数组的所有元素“一股脑”传递进来,大家还得规规矩矩使用数组指针。

int intArr[6]这种形式只能说明函数期望用户传递的数组有 6 个元素,并不意味着数组只能有 6 个元素,真正传递的数组可以有少于或多于 6 个的元素。

需要强调的是,不管使用哪种方式传递数组,都不能在函数内部求得数组长度,因为 intArr 仅仅是一个指针,而不是真正的数组,所以必须要额外增加一个参数来传递数组长度。

C语言为什么不允许直接传递数组的所有元素,而必须传递数组指针呢?

参数的传递本质上是一次赋值的过程,赋值就是对内存进行拷贝。所谓内存拷贝,是指将一块内存上的数据复制到另一块内存上。

对于像 int、float、char 等基本类型的数据,它们占用的内存往往只有几个字节,对它们进行内存拷贝非常快速。而数组是一系列数据的集合,数据的数量没有限制,可能很少,也可能成千上万,对它们进行内存拷贝有可能是一个漫长的过程,会严重拖慢程序的效率,为了防止技艺不佳的程序员写出低效的代码,C语言没有从语法上支持数据集合的直接赋值。

除了C语言,C++、Java、Python 等其它语言也禁止对大块内存进行拷贝,在底层都使用类似指针的方式来实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/198018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ocelot的单节点解决方案

ocelot的问题前面我们解决了consul的单节点的集群扩建。这里讨论如果在多客户端访问时&#xff0c;单网关也会有瓶颈。如果单台挂掉&#xff0c;那么也会麻烦&#xff0c;所以根据项目需要解决问题。ocelot多节点部署最简单的粗暴解决&#xff0c;多部署几台网关。但是我们需要…

mac环境和windows环境下GeoServer如何安装部署

geoserver是从事GIS行业都应当了解的一个gis服务器。 所以说学会geoserver是一个非常必要的事情。那么这篇文章呢我就带着大家来一起学习如何在Mac机器上和windows机器上安装并部署Geoserver。 首先不管是哪个环境我们都需要去官网上先下载安装包。 第一步我们要去geoserver的…

【计算机组成原理】y = a * b + c 的执行具体流程

文章目录1.2.2 认识各个硬件部件1. 主存储器的基本组成2. 运算器的基本组成3. 控制器的基本组成4. 计算机的工作流程1.2.2 认识各个硬件部件 1. 主存储器的基本组成 存储体&#xff1a;存放数据和指令地址寄存器&#xff1a;用来存放读取存储体数据时存放的具体位置数据寄存器…

12、字符(串)输入、输出

目录 一、字符数据输入&#xff0f;输出 1. 字符数据输入 2. 字符数据输出 二、字符串输入&#xff0f;输出 1. 字符串输入函数 2. 字符串输出函数 一、字符数据输入&#xff0f;输出 1. 字符数据输入 字符数据输入使用的是getchar函数&#xff0c;其作用是从终端&…

前端遇到的问题

inputs-outputs https://angular.cn/guide/inputs-outputs 用于父组件与子组件间的值传递 在项目中引入核心组件 父组件在其html界面绑定属性 在子组件里通过Input传递值 具体里: 使用默认规则数组绑定固定值(比如id)的错误 这里两个ts文件之间传值,采用了一个get函数,…

微信小程序 view组件的基本使用

1.view基本理论 能看图就尽量减少文字提示&#xff0c;从图书可以看出ABC是纵向排列的。 为什么会纵向排列而不是横向排列&#xff0c;那是因为view是块元素&#xff0c;能占满整一行。 怎么让view块元素横向并排呢&#xff1f; 向上图一样横向排列&#xff0c;接下来教学从0…

Kerberos协议与认证数据包分析

Kerberos协议 Kerberos是一种在开放的非安全网络中认证并识别用户身份信息的方法, 它旨使用密钥加密技术为客户端/服务端应用程序提供强身份认证。 目前主流的Kerberos版本是2005年的RFC4120标准的Kerberos v5, Windows、Linux和MacOs均支持Kerberos协议。Kerberos基础 Kerbe…

Quartz入门看这一篇文章就够了

第一章 Quartz简介 第一节 Quartz是什么? 1Quartz [kwɔːts]是一个完全由Java编写的开源的作业调度框架第二节 Quartz可以用来做什么? 比如说买火车票下单之30分钟之后,查看是否付款付款完成之后,在乘车日期的时候是否乘车或者每个月1号扣房贷每个月20号自动还信用卡想定时…

为什么要使用采购管理软件 采购管理软件推荐

在企业发展道路上&#xff0c;采购部门是一个非常重要的组织&#xff0c;它会直接影响到企业的经济效益。企业在采购活动中&#xff0c;如果还是采用传统线下的采购方式&#xff0c;那么很容易导致采购信息不集中&#xff0c;效率低&#xff0c;出错率高&#xff0c;最终损害企…

爱情呼叫转移-深度广度遍历合集

1.这件事是特殊的&#xff0c;还是普遍的&#xff1f; 工作中常常会遇到各种各样的问题&#xff0c;不管黑猫白猫&#xff0c;抓到老鼠就是好猫。哪只猫好&#xff0c;往往需要对比分析。 如何做数据对比&#xff0c;需要加入哪些数据来分析&#xff0c;在哪里进行数据对比&am…

查找 二分查找 (终极巩固)

二分条件&#xff1a; 1) 序列有序 2&#xff09;支持随机访问 二分思想&#xff1a; 大体思想是二分之后如果目标值在左侧&#xff0c;则中间包括右边区间所有pass掉 right mid - 1; 目标在右侧&#xff0c;则中间包括左边所有pass left mid 1; 注意点 left < rig…

Python Fiddler抓包工具教学,获取公众号(pc客户端)数据

前言 今天来教大家如何使用Fiddler抓包工具&#xff0c;获取公众号&#xff08;PC客户端&#xff09;的数据。 Fiddler是位于客户端和服务器端的HTTP代理&#xff0c;是目前最常用的http抓包工具之一。 开发环境 python 3.8 运行代码pycharm 2021.2 辅助敲代码requests 第三方…

VS2022 开发Qt之修改软件图标

开发环境本次实验使用的开发环境是win10 64位系统 IDE使用VS2022,Qt版本是Qt5,15.写博客背景最近再练习使用VS开发Qt,到修改软件图标的事情.在网上搜索了一番大部分修改图标的都是基于Qt自带的编译器,由于本人使用的VS的IDE和自带的编译器设置方法有所不同,在一番查找实验后还整…

【论文学习】YOLOv1-YOLOv4

文章目录You Only Look Once,Unified ,Real-Time Object DetectionAbstractIntroductionUnified DetectionNetwork DesignTrainingInferenceLimitations of YOLOComparison to Other Detection SystemsYOLO9000:Better,Faster,StrongerAbstractIntroductionBetterBatch Normali…

【C++之类和对象】日期类的实现

目录前言一、日期类的基本样式二、构造函数三、拷贝构造函数四、赋值运算符重载五、日期比较1. 判断一个日期是否小于另一个日期2. 判断一个日期和另一个日期是否相等3. 判断一个日期是否小于等于另一个日期4. 判断一个日期是否大于另一个日期5. 判断一个日期是否大于等于另一个…

独孤九剑xss通关教程

独孤九剑xss通关教程 独孤九剑第一式&#xff1a; 这里过滤了 () 构造payload&#xff1a; ?data"><svg><script>%26%23x65%3B%26%23x76%3B%26%23x61%3B%26%23x6c%3B%26%23x28%3B%26%23x6c%3B%26%23x6f%3B%26%23x63%3B%26%23x61%3B%26%23x74%3B%26%23…

开门红,农民大衣哥兔年第一条祝福,为何在百万艺人中选择杨语莲

俗话说&#xff1a;人逢喜事精神爽。这句话用到农民歌唱家大衣哥身上&#xff0c;就再贴切不过了&#xff0c;因为在新年即将来临之际&#xff0c;他的儿子小伟又一次结婚了。大衣哥是一个非常接地气的明星&#xff0c;这些年来他无绯闻不炒作&#xff0c;堪称为娱乐圈的楷模&a…

开学季,送初三学生什么礼物最实用?2023学生护眼台灯分享

春节的新学期即将到来&#xff0c;送给初中孩子什么礼物比较好呢&#xff0c;还是要对学习有所帮助的&#xff0c;还需要培养孩子的兴趣&#xff0c;在挑选礼物时&#xff0c;也是斟酌了很久&#xff0c;面对现在很多孩子的有近视问题&#xff0c;在我国的近视人数达到7亿人&am…

java面试题(十一)IO流篇

2.21 请介绍TreeMap的底层原理 参考答案 TreeMap基于红黑树&#xff08;Red-Black tree&#xff09;实现。映射根据其键的自然顺序进行排序&#xff0c;或者根据创建映射时提供的 Comparator 进行排序&#xff0c;具体取决于使用的构造方法。TreeMap的基本操作containsKey、g…

三维重建——商汤NeuralRecon算法详解与论文解读

论文地址:https://arxiv.org/abs/2104.00681 1.三维重建任务概述 三维重建,就是将2D的图片信息重建为3D的信息。应用领域广泛。可以应用于原型设计、虚拟现实等。 2.三维重建基础 (1) 相机成像 相机成像一般是小孔成像的原理,f就是焦距,o就是光圈;右图为光圈大小对清晰…