函数传参数组时,使用数组形参的本质

news2024/12/22 13:42:07

c语言中函数的调用分为两种方式:传址调用、传值调用。

传值调用我们都知道就是将实参的值传送给被调函数,让被调函数的形参接收这个值,从而形参内存中的数据就变成了实参的一份拷贝。

而传址调用则是将实参的地址传送过去,然后令实参为一指针变量,这个指针变量接收实参的地址,从而使这个指针变量内保存的数据变成实参的地址。

传值调用的功能更加强大,因为它是一个指针,可以通过解引用直接访问到实参。

但是,随着我了解了函数栈帧的开辟以及形参的压栈,我发现了一个问题:

就是这个函数

 

请问,这个函数里面的形参到底是个什么东西,它真的像它的表面一样,是个数组形参吗? ArrInit函数栈帧空间进行开辟时,压栈的是什么呢?

数组是如何进行传参的?在学校中,我们的老师给我们讲的是:我们可以理解为因为数组名等于首地址,将数组名传送过去之后,形参数组名接受到这个地址,那么两者就共用同一块空间。

是的,老师为了让我们不太混乱,给了我们一个挺好的理解。但是这个理解我现在有点感觉不太对了。首先,数组名是首地址,是一个常量,一个指针常量。它不是变量!这个很重要,数组名一般情况下都是数组的首地址,是一个常量,不能作为一个变量来使用。只有两种情况下数组不是数组的首地址:

第一:使用sizeof计算数组大小时,此时数组名不是首地址,数组名此时就是一个抽象的变量名,类似于int a = 10 中的a这个变量名, 而它所代表的空间就是数组一整块空间。所以sizeof求出来的就是这一整块空间的大小。

第二:&数组名。 &是取地址符号, 取的是一个对象的地址。那么当&加数组名时,取出来的就是一个数组的地址。数组的地址,是一种指针类型,需要用数组指针接收(数组指针,一种情况就是用在此场景,另一种常见场景就是二维数组的传参)

除了以上两种情况,其他情况下数组名都作为首地址进行处理。

带着这个结论,我们再看上面的两个问题

既然数组名等于函数首地址,那么函数调用传参传过去的必定是一个地址。也就是传址调用。那么接收这个地址的必定是一个指针。( 数组名是一个常量,不可能用来接收,所以形参处的数组名不可能与实参的数组名代表同一地址。) 既然是传址调用,那么形参一定是个指针。

所以,我们不妨假设, int farr【10】这里其实不是一个数组,而是一个指针。那么如何证明我们的假设是否成立,我们只要使用sizeof。 使用sizeof进行计算farr这个对象的大小时,假如我们的假设成立,那么sizeof计算出来的就是4 / 8(取决于你的环境)。假如我们的假设不成立, 它如果还是个数组,那么farr身为数组名,使用sizeof进行计算,就一定是40.

现在我们来看一下结果:

结果是8, 我们的假设成立。证明farr确实是一个指针变量。至于为什么形参写成int farr[10]的形式,结果还是一个指针,我认为可能是因为这样:

我们都知道*(arr + i) = arr[i];这里我认为同样可以这样理解,farr【10】其实只是一个指针解引用的形式。而且其实farr【10】里面的这个10,在这里无论是任何数,它都没有语法问题。这其实就说明这个10是一个没有意义的数字。要知道,函数调用的形参是一份拷贝,是要进行压栈的,拷贝的数据越大,占用内存也就越大。传送数组函数进行接收时,必定要创建一个形参,假如创建一个相同的数组,这个空间就占用太大了,而如果是一个指针的话,空间花费就少了太多。而运用方式相差不大。从这个方面考虑,就大概可以理解为什么这个数组的形参默认被降维成为一个指针了。

所以,我对于我之前的疑问就有了一个自己的答案,函数的数组形参其实并不是一个数组。形参因为压栈要进行拷贝占用空间,出于节省的考虑。将形参降维成了一个指针。而压栈的必定也不会是整个数组,本质上只是一个指向实参数组首地址的指针

 

 

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

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

相关文章

IaC基础设施即代码:Terraform 创建 docker 网络与容器资源

目录 一、实验 1.环境 2.Terraform查看版本 3.Linux主机安装Docker 4.Terraform使用本地编译(In-house)的Providers 5.Docker-CE 开启远程API 6. Linux主机拉取镜像 7.Terraform 创建docker 网络资源 8.Terraform 创建docker 容器资源 一、实验 …

8.3 Springboot整合Redis 之Jedis方式

文章目录 前言一、Maven依赖二、新增子Module:tg-book-redis三、Jedis配置类3.1 Jedis连接池核心配置说明四、Jedis 工具类五、新增controller测试前言 Jedis是Redis官方推荐的Java客户端连接工具,用法非常简单,Jedis的API与Redis的API可以说是一模一样,所以非常有利于熟悉…

【K8S 云原生】K8S的包包管理器-helm

目录 一、helm概念 1、什么是helm 2、helm的概念: 二、实验部署: 1、安装helm: 2、对chart仓库的基本使用: 2.1、查看和更新chart仓库 2.2、安装chart 2.3、卸载chart: 3、helm自定义模版: 3.1、…

未来趋势:视频美颜SDK与增强现实(AR)的融合

当下,视频美颜SDK不断演化,成为用户记录和分享生活时不可或缺的一部分。同时,增强现实技术也以其独特的沉浸感和交互性受到青睐,被广泛应用于游戏、教育、医疗等领域。 一、视频美颜与AR的结合 1.实时美颜的AR增值体验 借助AR的…

【Springboot】日志

1.日志的使用 日志主要用于记录程序运行的情况。我们从学习javase的时候就使用System.out.println();打印日志了,通过打印的日志来发现和定位问题,或根据日志来分析程序运行的过程。在Spring的学习中,也经常根据控制台的⽇志来分析和定位问题 。 日志除…

《WebKit 技术内幕》学习之七(1): 渲染基础

《WebKit 技术内幕》之七(1): 渲染基础 WebKit的布局计算使用 RenderObject 树并保存计算结果到 RenderObject 树。 RenderObject 树同其他树(如 RenderLayer 树等),构成了 WebKit 渲染的为要基础设施。 1…

w23靶场安装

一、实验环境 服务器:phpstudyv8.1.13 靶场:Bees二、实验目的 提供一个靶场环境 三、实验步骤 bees靶场安装 1.启动小皮的apache和mysql 2.在小皮V8.1.1.3版本上创建bees网站,选择的php版本最好在5.x,不然会有php解析错误。…

Windows系统如何修改Nginx配置实现远程访问多个本地站点

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…

samba服务搭建,并将共享目录映射到windows

系统版本:centos7 1、centos 安装samba yum -y install samba 2、查看安装信息 rpm -qa |grep samba 3、设置开机自启动 systemctl enable smb.service systemctl enable nmb.service 4、设置samba服务器配置文件 sudo vi /etc/samba/smb.conf 注意&#…

mysql进阶-执行计划

目录 1. 概念 2. 使用 3. 具体相关字段含义 3.1 id 3.2 select_type 3.3 table 3.4 partition 3.5 type 3.6 possible_key 3.7 key 3.8 key_len 3.9 ref 3.10 row 3.11 filtered 3.12 extra 1. 概念 一条语句通过优化器之后,会生成具体的执行计划用…

qt-c++多窗口编程

1、QMessageBox 消息对话框 QMessageBox继承自QDialog,显示一个模态对话框。用于用户前台信息通知或询问用户问题,并且接收问题答案。 QDialog再Qt源码中,派生类往往都是一些在特定场合下使用的预设好的对话框窗口。这些窗口无需创建对象&…

PaddleDetection学习3——使用Paddle-Lite在 Android 上部署PicoDet模型(fp16)

使用Paddle-Lite在 Android 上运行PicoDet模型(fp16) 1. 环境准备2. 部署步骤2.1 下载Paddle-Lite-Demo2.2 打开 picodet_detection_demo项目2.2.1 修改build.gradle,配置国内镜像仓库2.2.2 NDK 配置错误问题2.2.3 gradle.properties文件配置…

PaddleOCR实现对表格的提取

1、背景 PaddleOCR: 基于飞桨的OCR工具库,包含总模型仅8.6M的超轻量级中文OCR,单模型支持中英文数字组合识别、竖排文本识别、长文本识别。同时支持多种文本检测、文本识别的训练算法。对pdf/word里的表格中识别出有效信息具有重要意义,比如…

OpenSource - 文件在线预览模块(多格式转 PDF 文件)

文章目录 文件在线预览模块(多格式转PDF文件)现已支持格式如下界面展示运行方式接口介绍文件上传文件转 PDF文件转图片文件转SVG 参数配置其他说明项目关联关键词文档转换预览技术说明同步转换异步转换 主要技术乱码问题处理帮助文档 前端预览弹出层用法…

uniapp开发小程序如何获取用户地理位置

1、需求说明 需求&#xff1a;点击按钮获取当前微信位置&#xff0c;以及点击拒绝授权后&#xff0c;下次点击还可以拉起授权窗口&#xff1b; 2、言归正传 1、编写代码 模板部分 <template><view><button type"" click"getLocation"&…

hugo的常规使用操作

hugo的常规使用操作&#xff08;不断完善中&#xff09; 找到theme主题中config.toml 一般都会通过theme中复制到自己项目的config.toml中做修改和补充&#xff0c;来完善不同的业务需求 Hugo静态资源载入逻辑 原理 将图片信息放到static中&#xff0c;但是在文章中写的时…

入门教程:使用 Postman 发送 post 请求

Postman 是一个实用的开发工具&#xff0c;它让发送各类 POST 请求成为了可能&#xff0c;包括文本、JSON、XML 以及文件等。开发者利用此工具不仅能够检验API的功能性&#xff0c;还能仿真客户端的请求行为&#xff0c;进而深入了解客户端如何与 API 进行互动。 HTTP 协议中的…

v38.条件结构

1.if-else 2.嵌套if结构 第二个if是嵌套在第一个if里面的&#xff0c;不能独立实现程序。存在依赖关系。 3.else if 不存在依赖关系。 4. printf函数是属于if/else 语句的&#xff0c;加不加大括号&#xff5b;&#xff5d;效果是一样的 5. 也就是说if的管辖范围只能是条件后…

服务器感染了.wis[[Rast@airmail.cc]].wis勒索病毒,如何确保数据文件完整恢复?

导言&#xff1a; 在当今数字化的时代&#xff0c;恶意软件攻击已经变得越来越复杂和狡猾&#xff0c;[[MyFilewaifu.club]].wis [[backupwaifu.club]].wis[[Rastairmail.cc]].wis勒索病毒是其中的一种新威胁。本文91数据恢复将深入介绍[[MyFilewaifu.club]].wis [[backupwaif…

大数据开发之Spark(入门)

第 1 章&#xff1a;Spark概述 1.1 什么是spark 回顾&#xff1a;hadoop主要解决&#xff0c;海量数据的存储和海量数据的分析计算。 spark是一种基于内存的快速、通用、可扩展的大数据分析计算引擎。 1.2 hadoop与spark历史 hadoop的yarn框架比spark框架诞生的晚&#xff…