【C语言】深入理解指针(3)数组名与函数传参

news2024/11/20 3:34:07

 


目录

(一)数组名的理解

(1)数组名是数组首元素的地址 

(2)两个例外

(二)函数内数组传参

(1)一维数组传参 

(2)二维数组传参 

(3)三维及高维数组传参


 

正文开始——数组与指针是紧密联系的

(一)数组名的理解

(1)数组名是数组首元素的地址 

int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *parr = &arr[0];

        上述代码通过&arr[0] 的方式得到了数组第一个元素的地址,但其实数组名本身就是一个地址,并且是数组首元素的地址。

代码1:


#include<stdio.h>
int main()
{
	int arr[6] = { 1,2,3,4,5,6};
	printf("%p\n",arr);
	printf("%p\n",&arr[0]);
	return 0;
}

结果:

        数组名与数组首元素的地址打印出的结果是一样的。于是,数组名就是数组首元素(第一个元素)的地址。

(2)两个例外

代码2:

#include <stdio.h>
int main()
{


    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    printf("%d\n", sizeof(arr));


    return 0;
}

结果:

         令我们出乎所料的是,这里的数组名不再是数组首元素的地址,而是表示整个数组。

对于代码中出现的数组名,不违背数组名是数组第一个元素的的地址,也就是说:

        数组名是数组首元素的地址是对的,但是有两个例外:

        • sizeof(数组名),sizeof中单独放数组名,这里的数组名代表整个数组,sizeof计算的是整个数组的大小,单位是字节
        • &数组名,这的数组名代表整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)

        除此之外,其他地方使用数组名,都代表的是数组首元素的地址。

那么,数组名与&数组名具体有什么区别?

        通过指针运算就可以体现出他们的区别:

代码3:

printf("&arr[0] = %p\n", &arr[0]);

printf("&arr[0]+1 = %p\n", &arr[0]+1);

printf("arr = %p\n", arr);

printf("arr+1 = %p\n", arr+1);

printf("&arr = %p\n", &arr);

printf("&arr+1 = %p\n", &arr+1);

 结果:

        &arr[0] 和 &arr[0] + 1 相差4个字节,arr 和 arr + 1 相差 4个字节,原因是&arr[0] 和arr 都是数组arr 首元素的地址,通过指针运算 +1 就是跳过一个int型的元素(也就是跳过4个字节)。

        &arr 和 &arr + 1 相差40个字节,原因是&arr是数组的地址,指针运算 + 1 就是跳过整个数组 int   [10] 型元素(也就是10个整形,40个字节)。


(二)函数内数组传参

(1)一维数组传参 

         相信你一定使用过冒泡排序吧;

        将数组(传址)和数组内元素个数传给函数,

​
int main()
{
    int arr[10] = {5,4,8,7,9,6,3,2,1,0};

    int sz1 = sizeof(arr)/sizeof(arr[0]);

    Bobble_sort(arr,sz1);

    Print();

return 0;
}

​

就会得到排序好的数组。

        观察上述操作,我们都是在函数外部计算数组的元素个数,那我们可以把数组传给⼀个函
数后,函数内部求数组的元素个数吗?
 

#include <stdio.h>

void test(int arr[])
{

    int sz2 = sizeof(arr)/sizeof(arr[0]);

    printf("sz2 = %d\n", sz2);

}

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;
}

结果:(在x86下)

         为什么传给函数的是数组,结果sizeof计算整个数组的的大小 = 4 字节呢?

        这就要学习数组传参的本质了,上个小节我们学习了:数组名是数组首元素的地址;那么在数组传参的时候,传递的是数组名,也就是说数组传参本质上传递的是数组首元素的地址。


        所以函数形参的部分理论上应该使用指针变量来接收首元素的地址。

void Bobble_sort(int* p,int sz)
{
    .......
}


int main()
{

    int arr[5] = {1,2,3,4,5};

    int sz = sizeof(arr)/sizeof(arr[0]);

    Bobble_sort(arr,sz);

    return 0;
}

那么在函数内部我们写sizeof(arr) 计算的是⼀个地址的大小(单位字节)而不是数组的大小(单位字节)。正是因为函数的参数部分是本质是指针,所以在函数内部是没办法求的数组元素个数的。

(2)二维数组传参 

         二维数组传参,以上的结论仍成立:

           数组传参本质上传递的是数组首元素的地址。

二维数组的首元素,不再是一个基本的数据类型,而是一个数组类型。

什么是数组类型?

如果一个数组是整形数组,元素是5个整形,那么他的类型就是( int    [5] )类型。

二维数组首元素的地址其数据类型就是(int  (*)[5])类型。

 那么在主函数内(未传参)sizeof(二维数组的数组名)计算的就是整个二维数组大小;

传参后,sizeof(二维数组名)的结果就是指针(int  (*)[5])的大小了。(所有类型,函数,其地址的大小是一定的)

(3)三维及高维数组传参

        仍然满足   数组传参本质上传递的是数组首元素的地址。

这里我们来看一段代码:

#include<stdio.h>

void PR(int (*p)[3][3])
{
	
}
int main()
{
	int arr[3][3][3];
	PR(arr);
	return 0;
}

        解释:

        数组arr的首元素类型是int    [3][3],在传参的时候,可以用指针类型int(*)[3][3]来接收,类型是照应的。这也说明 arr传递的是首元素的地址


完~

未经作者同意禁止转载

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

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

相关文章

以太网交换基础VLAN原理与配置

目录 7.以太网交换基础 7.1.以太网协议 7.2.以太网帧介绍 7.3.以太网交换机 7.4.同网段数据通信全过程 8.VLAN原理与配置 8.1.VLAN的基本概念 8.2.VLAN的应用 7.以太网交换基础 7.1.以太网协议 以太网是当今现有局域网(Local Area Network,LAN)采用的最通用的通信协议…

git使用指南——以gitlab为例

注册gitlab 自行注册 新建项目 选择新建一个空白的项目 上传项目 clone项目地址到本地 执行完之后&#xff0c;会在目录下生成如下内容&#xff1a;进入里面&#xff0c;选择.git&#xff0c;要上传的内容&#xff08;资料或代码复制到该目录下&#xff09;&#xff1a;…

界面组件DevExpress .NET MAUI中文教程 - 如何优化手机屏幕空间?

DevExpress拥有.NET开发需要的所有平台控件&#xff0c;包含600多个UI控件、报表平台、DevExpress Dashboard eXpressApp 框架、适用于 Visual Studio的CodeRush等一系列辅助工具。 获取DevExpress v23.2正式版下载 Bottom Sheet是一个组件&#xff0c;它显示固定在屏幕底部的…

LeetCode:376.摆动序列

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;算法_仍有未知等待探索的博客-CSDN博客 题目链接&#xff1a;376. 摆动序列 - 力扣&#xff08;LeetCode&#xff09; 一、题目 如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称…

【排序5】基数排序:数字的组织与整理艺术

&#x1f3a1;基数排序 &#x1f38a;1、基本思想&#x1f38a;2、基本步骤&#x1f38a;3、代码示例&#x1f38a;4、特性总结 &#x1f38a;1、基本思想 基数排序&#xff08;Radix Sort&#xff09;是一种非比较排序算法&#xff0c;它根据数字的每一位来对元素进行排序。它…

提示unzip :commad not found; 安装unzip教程

1.当使用unzip解压时 提示&#xff1a; unzip :commad not found; 2.安装命令 sudo yum install unzip 3.输入 y 确认 4.提示&#xff1a;完成 5.输入 unzip 文件名 解压-验证 6.完成

34.基于51单片机的智能停车位计时收费系统设计

一、系统功能介绍&#xff1a; 本设计基于 RFID智能识别和高速的视频图像和存储比较相结合&#xff0c;通过计算机的图像处理和自动识别&#xff0c;对车辆进出停车场的收费、车牌识别和车位诱导等&#xff0c;以实现停车场全方位智能管理。 本设计是以AT89C51 型单片机为主控芯…

Kubernetes (十七) 资源监控

一. 资源监控 二. metrics-server资源下载配置 官网:资源下载&#xff1a;http…

搭建Mybatis环境

1.导入依赖 pom.xml <dependencies> <!-- Mybatis依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency> <!-- Mysql依…

Tonka Finance 测试网活动,开启新铭文时代财富之门

Tonka Finance 是铭文赛道首个借贷市场&#xff0c;通过搭建一套铭文资产借贷质押方案&#xff0c;为铭文资产以借贷的形式释放价值、捕获流动性等方面提供了基础。作为铭文赛道最重要的基建设施之一&#xff0c;Tonka Finance 在面向市场后备受关注&#xff0c;并迅速作为铭文…

【UE】在控件蓝图中通过时间轴控制材质参数变化

效果 步骤 1. 新建一个控件蓝图和一个材质 2. 打开材质&#xff0c;设置材质域为用户界面&#xff0c;混合模式设置为“半透明” 在材质图表中添加两个参数来控制材质的颜色和不透明度 3. 对材质创建材质实例 4. 打开控件蓝图&#xff0c;在画布面板中添加一个图像控件 将刚…

vue常用指令(v-html)

一、v-html 指令 作用: 获取文本数据设置元素的innerHTML&#xff0c;此为和v-text的区别 二、代码演示 1、获取普通文本数据 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewpor…

32个Java面试必考点-08高并发架构基石-缓存

本课时介绍缓存相关的知识点以及 Memcache 和 Redis 这两个最常使用的缓存。重点学习以下三个方面的内容&#xff1a; 1.使用缓存时常遇到的典型问题&#xff1b; 2.Memcache 的内存结构&#xff1b; 3.Redis 相关的知识点以及 Redis 常用结构的实现。 缓存知识点 类型 缓…

day34WEB 攻防-通用漏洞文件上传黑白盒审计逻辑中间件外部引用

目录 一&#xff0c;白盒审计-Finecms-代码常规-处理逻辑 黑盒思路&#xff1a;寻找上传点抓包修改突破获取状态码及地址 审计流程&#xff1a;功能点-代码文件-代码块-抓包调试-验证测试 二&#xff0c;白盒审计-CuppaCms-中间件-.htaccess 三&#xff0c;白盒审计-Metin…

XCTF:Normal_RSA[WriteUP]

从题目中获取到两个文件 flag.enc内容是通过rsa加密了的密文 pubkey.pem是rsa公钥&#xff0c;加密者利用这个文件对flag原文进行了加密 如果对rsa加密算法不了解的可以补一下教学视频 数学不好也能听懂的算法 - RSA加密和解密原理和过程_哔哩哔哩_bilibili 使用openssl对公…

使用dockers-compose搭建开源监控和可视化工具

简介 Prometheus 和 Grafana 是两个常用的开源监控和可视化工具。 Prometheus 是一个用于存储和查询时间序列数据的系统。它提供了用于监控和报警的数据收集、存储、查询和图形化展示能力。Prometheus 使用拉模型&#xff08;pull model&#xff09;&#xff0c;通过 HTTP 协议…

二、mongoose的使用,实现用户集合的操作

前言 mongodb&#xff1a;为了在node应用中与MongoDB交互&#xff0c;开发者需要使用MongoDB的驱动程序&#xff0c;所以安装的mongodb就是其驱动程序&#xff1b; mongoose: 是一个用于 MongoDB 的对象建模工具&#xff0c;提供了一个丰富的查询语言和许多其他功能&#xff0c…

pytest教程-7-用例前后置方法

上一小节&#xff0c;我们学习了pytest跳过测试用例的方法&#xff0c;本小节我们讲解一下pytest用例的前后置方法。 在unittest中就有前置setup和后置teardown来处理测试用例执行前的准备工作&#xff08;浏览器驱动实例化&#xff0c;数据库连接等&#xff09;以及执行后的处…

数据结构之位图与布隆过滤器

数据结构之位图与布隆过滤器 文章目录 数据结构之位图与布隆过滤器一、位图1、位图概念2、位图的实现3、位图的应用 二、布隆过滤器1、布隆过滤器的提出2、布隆过滤器概念3、布隆过滤器的插入4、布隆过滤器的查找5、布隆过滤器删除6、布隆过滤器优点7、布隆过滤器缺陷8、布隆过…

Vulnhub-dc6

信息收集 # nmap -sn 192.168.1.0/24 -oN live.port Starting Nmap 7.94 ( https://nmap.org ) at 2024-01-25 14:39 CST Nmap scan report for 192.168.1.1 Host is up (0.00075s latency). MAC Address: 00:50:56:C0:00:08 (VMware) Nmap scan report for 192.168.1.2…