当前位置: 首页 > news >正文

浅学指针(2)数组函数传值调用

系列文章目录

文章目录

  • 系列文章目录
  • 前言
  • 1. 指针的使⽤和传址调⽤
    • 结论:实参传递给形参的时候,形参会单独创建⼀份临时空间来接收实参,对形参的修改不影响实 参。
    • 那么这个时候,就要搬出指针大哥,在main函数中将a和b的地址传递给Swap函数,Swap函数⾥边通过地址间接的操作main函数中的a和b,像是把家(地址)搬到函数中,直接改变家里的东西(a, b的值)。
  • 2 .数组名的理解
    • 所以说:数组名就是数组⾸元素(第⼀个元素)的地址。
  • 3. 使⽤指针访问数组
  • 4 . 一维数组函数传参形本质
    • 接下来进入重点,⾸先从⼀个问题开始,我们之前都是在函数外部计算数组的元素个数,那我们可以把函数传给⼀个函数后,函数内部求数组的元素个数吗?
  • 5. ⼆级指针
    • 总结:2级指针是存放一级指针的地址
  • 6. 指针数组
    • 指针数组是存放指针的数组
    • 但是并非是2维数组,原因是模拟的数组并不连续,而数组在内存上是连续存放的。


前言

1. 指针的使⽤和传址调⽤

学习指针的⽬的是使⽤指针解决问题,那什么问题,⾮指针不可呢?

案例:写⼀个函数,交换两个整型变量的值
代码如下:

#include <stdio.h>
void Swap1(int x, int y)
{int tmp = x;x = y;y = tmp;
}
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("交换前:a=%d b=%d\n", a, b);Swap1(a, b);printf("交换后:a=%d b=%d\n", a, b);return 0;
}

输出结果:
在这里插入图片描述
这是为什么呢?
在这里插入图片描述

我们发现在main函数内部,创建了a和b,a的地址是0x00cffdd0,b的地址是0x00cffdc4,在调⽤Swap1函数时,将a和b传递给了Swap1函数,在Swap1函数内部创建了形参x和y接收a和b的值,但是x的地址是0x00cffcec,y的地址是0x00cffcf0,x和y确实接收到了a和b的值,不过x的地址和a的地址不⼀样,y的地址和b的地址不⼀样,相当于x和y是独⽴的空间,那么在Swap1函数内部交换x和y的值,⾃然不会影响a和b,当Swap1函数调⽤结束后回到main函数,a和b的没法交换。Swap1函数在使⽤的时候,是把变量本⾝直接传递给了函数,这种调⽤函数的⽅式我们之前在函数的时候就知道了,这种叫传值调⽤。

结论:实参传递给形参的时候,形参会单独创建⼀份临时空间来接收实参,对形参的修改不影响实
参。

所以Swap是失败的了。

那么这个时候,就要搬出指针大哥,在main函数中将a和b的地址传递给Swap函数,Swap函数⾥边通过地址间接的操作main函数中的a和b,像是把家(地址)搬到函数中,直接改变家里的东西(a, b的值)。

代码展示:

#include<stdio.h>
void Swap2(int*px, int*py)
{int tmp = 0;tmp = *px;*px = *py;*py = tmp;
}
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("交换前:a=%d b=%d\n", a, b);Swap1(&a, &b);printf("交换后:a=%d b=%d\n", a, b);return 0;
}

输出结果:
在这里插入图片描述
我们可以看到实现成Swap2的⽅式,顺利完成了任务,这⾥调⽤Swap2函数的时候是将变量的地址传递给了函数,这种函数调⽤⽅式叫:传址调⽤。

2 .数组名的理解

如下代码:

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

输出结果:
在这里插入图片描述

所以说:数组名就是数组⾸元素(第⼀个元素)的地址。

但是有两个例外:

• sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩,
单位是字节
• &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素
的地址是有区别的)
除此之外,任何地⽅使⽤数组名,数组名都表⽰⾸元素的地址。

还有一点,arr和&arr有啥区别:

#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };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);return 0;
}

输出结果:
在这里插入图片描述
这⾥我们发现&arr[0]和&arr[0]+1相差4个字节,arr和arr+1 相差4个字节,是因为&arr[0] 和 arr 都是⾸元素的地址,+1就是跳过⼀个元素。
但是&arr 和 &arr+1相差40个字节,这就是因为&arr是数组的地址+1 操作是跳过整个数组的。到这⾥⼤家应该搞清楚数组名的意义了吧。

3. 使⽤指针访问数组

有了前面知识,我们便可以使用指针访问数组啦!其实数组也相当于指针,如:*(p + 1)= arr[1],扩展
在这里插入图片描述
数组名arr是数组⾸元素的地址,可以赋值给p,其实数组名arr和p在这⾥是等价的。那我们可以使⽤arr[i]可以访问数组的元素,那p[i]是否也可以访问数组呢?`

#include <stdio.h>
int main()
{int arr[10] = {0};//输⼊int i = 0;int sz = sizeof(arr)/sizeof(arr[0]);//输⼊int* p = arr;for(i=0; i<sz; i++){scanf("%d", p+i);//scanf("%d", arr+i);//也可以这样写}//输出for(i=0; i<sz; i++){printf("%d ", p[i]);}return 0;
}

在第18⾏的地⽅,将*(p+i)换成p[i]也是能够正常打印的,所以本质上p[i] 是等价于 *(p+i)。

4 . 一维数组函数传参形本质

接下来进入重点,⾸先从⼀个问题开始,我们之前都是在函数外部计算数组的元素个数,那我们可以把函数传给⼀个函数后,函数内部求数组的元素个数吗?

展示如下:

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

输出结果:
在这里插入图片描述

很明显函数是没有正确获得数组元素个数的,上面我们学习了数组名是数组⾸元素的地址;那么在数组传的时候,传递的是数组名,也就是说本质上数组传参本质上传递的是数组⾸元素的地址。
所以函数形参的部分理论上应该使⽤指针变量来接收⾸元素的地址。

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

总结:⼀维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式.

5. ⼆级指针

在这里插入图片描述
要理解如下:

int main()
{int a = 30;int * pa = &a;//取出a的地址 * 表示pa是指针,指针的类型是int类型int * * ppa = &p;//ppa前的*表示ppa是指针,指针的类型是int *类型
}

2级指针的解引用
对上面案例分析,像是扒白菜一样,一层一层来,如下展示:
在这里插入图片描述

最终得到结果

总结:2级指针是存放一级指针的地址

6. 指针数组

指针数组是存放指针的数组

在这里插入图片描述
在这里插入图片描述
结合如上知识,那么指针是可以模拟数组的
扩展:指针数组模拟⼆维数组

#include <stdio.h>
int main()
{int arr1[] = {1,2,3,4,5};int arr2[] = {2,3,4,5,6};int arr3[] = {3,4,5,6,7};//数组名是数组⾸元素的地址,类型是int*的,就可以存放在parr数组中int* parr[3] = {arr1, arr2, arr3};int i = 0;int j = 0;for(i=0; i<3; i++){for(j=0; j<5; j++){printf("%d ", parr[i][j]);}printf("\n");}return 0;
}

图来展示:
在这里插入图片描述

parr[i]是访问parr数组的元素,parr[i]找到的数组元素指向了整型⼀维数组,parr[i][j]就是整型⼀维数组中的元素。

但是并非是2维数组,原因是模拟的数组并不连续,而数组在内存上是连续存放的。

都看到这里了,那就点个赞吧,学习大家

相关文章:

浅学指针(2)数组函数传值调用

系列文章目录 文章目录 系列文章目录前言1. 指针的使⽤和传址调⽤结论&#xff1a;实参传递给形参的时候&#xff0c;形参会单独创建⼀份临时空间来接收实参&#xff0c;对形参的修改不影响实 参。那么这个时候&#xff0c;就要搬出指针大哥&#xff0c;在main函数中将a和b的地…...

C++之unordered_map/set的使用

前面我们已经学习了STL中底层为红黑树结构的一系列关联式容器——set/multiset 和 map/multimap(C98). unordered系列关联式容器 在C98中, STL提供了底层为红黑树结构的一系列关联式容器, 在查询时效率可达到log2N,即最差情况下需要比较红黑树的高度次, 当树中的节点非常多时,…...

docker打包chatpdf(自写)

docker打包上传 docker build -t kitelff/chatpdf:v0.1 .##修改镜像名字 docker tag c2c1a0eb4e08 kitelff/chatpdf:v0.1## push docker push kitelff/chatpdf:v0.1上传文件&#xff0c;测试效果...

shell基础

一.Shell脚本编程概述 1.基本概念 将要执行的命令按顺序保存到一个文本文件&#xff1b; 给该文件可执行权限&#xff1b; 可结合各种Shell控制语句以完成更复杂的操作。 2.作用 Linux系统中的Shell是一个特殊的应用程序&#xff0c;它介于操作系统内核与用户之间&#x…...

力扣1038. 从二叉搜索树到更大和树(java,树的中序遍历解法)

Problem: 1038. 从二叉搜索树到更大和树 文章目录 题目描述思路解题方法复杂度Code 题目描述 给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。 提醒一下&#xff0c; 二叉搜索树 满足下列约束条件&#xff…...

使用正则表达式来判断一个字符串只是否包含数字

使用正则表达式来判断一个字符串只是否包含数字 1、第一种 import java.util.regex.Pattern;public class Main {public static void main(String[] args) {String inputString "12345";if (containsOnlyDigits(inputString)) {System.out.println("字符串只…...

C#Wpf关于日志的相关功能扩展

目录 一、日志Sink(接收器) 二、Trace追踪实现日志 三、日志滚动 一、日志Sink(接收器) 安装NuGet包&#xff1a;Serilog Sink有很多种&#xff0c;这里介绍两种&#xff1a; Console接收器&#xff08;安装Serilog.Sinks.Console&#xff09;; File接收器&#xff08;安装…...

亚马逊云科技AI创新应用下的托管在AWS上的数据可视化工具—— Amazon QuickSight

目录 Amazon QuickSight简介 Amazon QuickSight的独特之处 Amazon QuickSight注册 Amazon QuickSight使用 Redshift和Amazon QuickSightt平台构建数据可视化应用程序 构建数据仓库 数据可视化 Amazon QuickSight简介 亚马逊QuickSight是一项可用于交付的云级商业智能 (BI…...

MySQL安全性:用户认证、防范SQL注入和SSL/TLS配置详解

MySQL作为广泛使用的关系型数据库管理系统&#xff0c;安全性至关重要。在本篇技术博客中&#xff0c;我们将深入探讨MySQL的用户认证方式、防范SQL注入攻击的方法以及SSL/TLS加密的配置。 1. MySQL用户认证方式 MySQL支持多种用户认证方式&#xff0c;其中两种常见方式是cac…...

EMG肌肉信号处理合集 (一)

本文归纳了常见的肌肉信号预处理流程&#xff0c;方便EMG信号的后续分析。使用pyemgpipeline库 来进行信号的处理。文中使用了 UC Irvine 数据库的下肢数据。 目录 1 使用wrappers 定义数据类&#xff0c;来进行后续的操作 2 肌电信号DC偏置去除 3 带通滤波器处理 4 对肌电…...

学自动化测试?我劝你还是算了吧。。。

本人7年测试经验&#xff0c;在学测试之前对电脑的认知也就只限于上个网&#xff0c;玩个办公软件。这里不能跑题&#xff0c;我为啥说&#xff1a;自学软件测试&#xff0c;一般人我还是劝你算了吧&#xff1f;因为我就是那个一般人&#xff01; 软件测试基础真的很简单&…...

第一百七十八回 介绍一个三方包组件:SlideSwitch

文章目录 1. 概念介绍2. 使用方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"如何创建垂直方向的Switch"相关的内容&#xff0c;本章回中将 介绍SlideSwitch组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们…...

Windows任务管理器内存性能界面各个参数含义

任务管理器的内存性能界面提供了一些关键参数&#xff0c;这些参数可以帮助你了解系统中内存的使用情况。以下是一些常见的参数及其含义&#xff1a; 已提交&#xff08;Committed&#xff09;&#xff1a; 表示已分配的物理内存和虚拟内存的总和。已提交的内存包括当前正在使…...

深度学习人脸表情识别算法 - opencv python 机器视觉 计算机竞赛

文章目录 0 前言1 技术介绍1.1 技术概括1.2 目前表情识别实现技术 2 实现效果3 深度学习表情识别实现过程3.1 网络架构3.2 数据3.3 实现流程3.4 部分实现代码 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习人脸表情识别系…...

全职RISC-V芯片D1开发板使用adb串口COM连接设备和文件上传下载

将两个USB端口都连接到工作电脑 推荐使用ADB工具访问开发板&#xff0c;下载连接如下&#xff1a; Windows版本&#xff1a;https://dl.google.com/android/repository/platform-tools-latest-windows.zip Mac版本&#xff1a;https://dl.google.com/android/repository/pla…...

STM32笔记---RTC

目录 一、RTC简介 二、主要特性 三、功能描述 3.1 读RTC寄存器 3.2 配置RTC寄存器 四、BKP简介 五、RTC_Init() 1. 函数BKP_ReadBackupRegister 2.RCC_LSEConfig设置外部低速晶振&#xff08;LSE&#xff09; 3.RTC基本结构 5.RTC_Init()实现 6.time.h 一、R…...

C语言之strstr函数的使用和模拟实现

C语言之strstr函数的模拟实现 文章目录 C语言之strstr函数的模拟实现1. strstr函数的介绍2. strstr函数的使用3. strstr的模拟实现3.1 实现思路3.2 实现代码 1. strstr函数的介绍 函数声明如下&#xff1a; char * strstr ( const char * str1, const char * str2 ); strs…...

【间歇振荡器2片555时基仿真】2022-9-24

缘由multisim出现这个应该怎么解决吖&#xff0c;急需解决-嵌入式-CSDN问答 输出一定要有电阻分压才能前后连接控制否则一定报错。...

MySQL与PostgreSQL 的一些SQL

MySQL 1、MYSQL输出重定向 将SQL内容输出到文件 nohup mysql -h127.0.0.1 -uroot -ppassword -Ne "sql语句;" > /home/mysql/data/xxxxx.txt &2、时间格式转换 时间转换&#xff0c;转10位时间戳 select UNIX_TIMESTAMP(2021-02-27 00:00:00)SELECT …...

Spring 七大组件

文章目录 Spring 七大组件 Spring 七大组件 核心容器(Spring core) 核心容器提供Spring框架的基本功能。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean&#xff0c;它是工厂模式的实现。BeanFactory使用控制反转(IOC)模式…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

flow_controllers

关键点&#xff1a; 流控制器类型&#xff1a; 同步&#xff08;Sync&#xff09;&#xff1a;发布操作会阻塞&#xff0c;直到数据被确认发送。异步&#xff08;Async&#xff09;&#xff1a;发布操作非阻塞&#xff0c;数据发送由后台线程处理。纯同步&#xff08;PureSync…...

python打卡第47天

昨天代码中注意力热图的部分顺移至今天 知识点回顾&#xff1a; 热力图 作业&#xff1a;对比不同卷积层热图可视化的结果 def visualize_attention_map(model, test_loader, device, class_names, num_samples3):"""可视化模型的注意力热力图&#xff0c;展示模…...