那些 C语言指针 你不知道的小秘密 (3)

本篇会加入个人的所谓‘鱼式疯言’
❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.
🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!
在这里插入图片描述

前言

在上一篇文章中小编主要讲解了

  • 野指针:小编总结了野指针出现的情况并说明其应对 对策

  • assert 断言:小编带着大家试着怎么用 assert 并体会了 assert 防止野指针的益处

  • 传值调用与传址调用: 理解了 传值传址 调用的不同,并说明分别用于哪些 使用场景 更好

  • 二级指针:二级指针的理解,同时并知晓如何 定义解引用

在本篇文章中将继续 和友友们一起探访 指针 的小秘密, 这次咱们只要围绕着 指针数组 的关系展开更进一步的理解

那么友友们让我们开始这次美好的指针之旅吧 💕 💕 💕

目录

  1. 数组名的含义
  2. 数组名的实际运用
  3. 一维数组传参的本质
  4. 指针数组
  5. 指针数组的实际运用

一. 数组名的含义

<1>. 数组名的简介

小爱同学就有疑问了 🤔 🤔 🤔,数组名不就是个名字么,不是相当于 变量名 一样的么,怎么还有含义呢 ? ? ?
是的,是有含义的 ❤️ ❤️ ❤️

数组名啊 !一般而言,本质上的含义就是 首元素的地址
但也有 特殊情况 的出现,下面宝子们就和小编一起去发现吧

我们可以先来做个测试

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

在这里插入图片描述
我们发现数组名和数组首元素的地址打印出的结果一模一样,数组名就是数组首元素(第一个元素)的地

这时候小爱同学就会有疑问?数组名如果是数组首元素的地址,那下面的代码怎么理解呢?

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

在这里插入图片描述
输出的结果是:40,如果arr是数组首元素的地址,那输出应该的应该是 4 / 8 才对。
其实数组名就是 数组首元素(第一个元素) 的地址是对的,但是有两种特殊情况

sizeof(数组名)sizeof 中单独放数组名,这里的数组名表示 整个数组 ,计算的是 整个数组 的大小, 单位是 字节

& 数组名,这里的数组名表示整个数组,取出的是 整个数组 的地址 (整个数组的地址数组首元素的地址 是有区别的) 除此之外,任何地方使用数组名,数组名都表示首元素的地址。

鱼式疯言

&sizeof 喜欢 搞特殊 ,贪心的想得到 数组的全部 ,其他都很知足,只需要数组 首元素的地址

#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);//取地址数组名printf("&arr    = %p\n", &arr);return 0;
}

在这里插入图片描述
三个打印结果一模一样,那小爱同学又纳闷了,那 arr&arr 有啥区别呢 ? 😣 😣 😣

最后小小的证明一下小编的说的到底有没有依据吧

#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//取地址首元素并 +1printf("&arr[0] = %p\n", &arr[0]);printf("&arr[0]+1 = %p\n", &arr[0] + 1);//数组名并 +1printf("arr = %p\n", arr);printf("arr+1 = %p\n", arr + 1);//取地址数组名并 +1printf("&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 就是跳过 4个字节(一个元素)。

但是 &arr&arr+1 相差 40(十六进制的地址就相差28) 个字节

这就是因为 &arr是数组的地址,+1 操作是跳过整个数组的。

到这里大家应该搞清楚 数组名 的意义了吧。
数组名是 数组首元素 的地址,但是有 2种 特殊情况

二. 数组名的实际运用

当我们需要输入输出数组时 , 我猜小爱同学可能会这样写

#include <stdio.h>
int main()
{int arr[10] = { 0 };//输入int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);//输入for (i = 0; i < sz; i++){scanf("%d", &arr[i]);}//输出for (i = 0; i < sz; i++){printf("%d ",arr[i]);}return 0;
}

在这里插入图片描述
当我们好学的小爱同学,看看小编这样写是不是也可以呢 💕 💕 💕

#include <stdio.h>
int main()
{int arr[10] = { 0 };//输入int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);//输入for (i = 0; i < sz; i++){//利用数组名是首元素地址//数组名在 + i 地址进行右移scanf("%d", arr + i);//scanf("%d", &arr[i]);//也可以这样写}//输出for (i = 0; i < sz; i++){//得到每个元素的地址//解引用打印数据printf("%d ", *(arr + i));//printf("%d ",arr[i]);//也可以这样写}return 0;
}

在这里插入图片描述
是的,友友们这下就明白原来我们数组的输入输出还能这样玩啊 😎 😎 😎
输入时

  1. 对该下标的元素进行 &
  1. 利用数组名是 首元素 的地址,进行 指针加减偏移 来操作

输出时:

  1. 除了我们想数组的下标访问
  1. 利用数组名是 首元素的地址 ,再 指针加减偏移 ,我们也可以通过得到我们 *每一个元素的的地址 *,来 * 解引用访问

鱼式疯言

*(arr+i) <==> &arr[i]

arr+i <==> &arr[i]

三. 一维数组传参的本质

数组我们学过了,之前也讲了,数组是可以传递给函数的,这个小节我们讨论一下一维数组传参的本质。
首先小伙伴可以思考一个问题 ? ? ?
我们之前都是在 函数外部 计算数组的元素个数
那我们可以把函数传给一个函数后, 函数内部 求数组的元素个数吗?
不妨让我们试一下吧 😃 😃 😃

<1>. 函数外部求数组长度

int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//在 test 函数外部求数组长度int sz1 = sizeof(arr) / sizeof(arr[0]);// 验证其大小printf("数组长度为 : %d\n", sz1);//test(arr);return 0;
}

在这里插入图片描述
在函数外部是完全正确的,没有问题 。

<2>. 函数内部

void test(int arr[10])
{int sz1 = sizeof(arr) / sizeof(arr[0]);printf("数组长度为 : %d\n", sz1);
}int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };test(arr);return 0;
}

在这里插入图片描述
我们发现在函数内部是没有正确获得数组的元素个数。
小爱同学就深思了,这到底是什么原因呢 ? ? ?
竟然我们今天要学习 数组传参的本质 ,那这个 内在的原因 肯定 和 数组传参 脱不了干系

友友们可以思考下
我们上一节提过数组名本质上是啥,是首元素的地址吧
那么有没有一种可能数组名在传参的时候根本没有把整个数组传过去,而是传了 首元素的地址
居然我们提出了猜想,不妨我们用代码来验证下吧

#include<stdio.h>// 参数写成数组形式,本质上还是指针
void test(int arr[])
{//验证一下//在 X86 的环境下 //一个指针大小是4个字节printf("%d\n", sizeof(arr));
}int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };test(arr);return 0;
}

在这里插入图片描述
猜想验证成功,宝子们真聪明 💖 💖 💖

实践证明,我们本质上数组传参本质上传递的是数组首元素的地址

如果是这样子的话,那么我们的代码以后是否可以这样写呢 ! ! !

#include<stdio.h>
// 参数写成指针形式
void test1(int* arr)
{printf("%d\n", sizeof(arr));//计算一个指针变量的大小for (int i = 0; i < 10; i++){printf("%d ", *(arr + i));}}int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };test1(arr);return 0;
}

在这里插入图片描述
小伙伴快看这样写是不是也是种思路呢! ! !

但是,我们知道了本质,

这不禁也知道sizeof(arr) 计算的是一个地址的大小(单位字节)而不是数组的大小(单位字节)。

正是因为函数的参数部分是本质是 指针,所以在函数内部是没办法求的 数组元素个数

那我们该怎么解决呢,如果是这样的 😣 😣 😣

<3>. 传参方案

唯一的解决办法就是把对应的数组长度现在函数外部求好,利用 参数 传过去。

#include<stdio.h>// 参数写成指针形式
// sz 来接收数组长度
void test1(int* arr,int sz)
{//利用最大长度来输出打印我们的数组元素for (int i = 0; i < sz; i++){printf("%d ", *(arr + i));}}int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };// 函数外部求数组长度int slz = sizeof(arr) / sizeof(arr[0]);// 传入 slz 长度test1(arr, slz);return 0;
}

在这里插入图片描述

鱼式疯言

一维数组传参还是 首元素地址 ,数组长度先算好,额外加一份 参数再传

四. 指针数组

<1>. 指针数组的简介

首先我们来思考一个问题

指针数组是指针还是数组?

友友们可以类比一下

整型数组 ,是存放 整型 的数组

字符数组 是存放 字符 的数组

指针数组 呢?是存放 指针 的数组。

C语言中,指针数组是指一个数组,它的每个元素都是一个指针变量。每个指针变量可以指向不同的数据类型或对象
指针数组可以声明为以下形式:

dataType *arrayName[size];

dataType 表示指针变量所指向的 数据类型

arrayName 是数组的 名称

size 是数组的 大小

在这里插入图片描述
小爱同学是不是还是有点困惑呢 😣 😣 😣
没关系 没关系
不妨我们画个图理解一下吧 ! ! !
在这里插入图片描述

  • 指针数组的每个元素都是用来存放 地址(指针) 的。
    如下图 :
    在这里插入图片描述

指针数组的每个 元素地址 ,又可以 指向 一块区域。

鱼式疯言

很多个 相同类型指针 哪里放,指针数组 管饭吃

五. 指针数组的实际运用

想必大家都学过二维数组吧,如果让宝子们写个二维数组,你可能会这样写 ! ! !

<1>. 二维数组

 #include<stdio.h>int main()
{//二维数组初始化int a[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };int i = 0,j=0;//外循环为行数for ( i = 0; i < 3; i++){//内循环为列数for ( j = 0; j < 4; j++){printf("%d ", a[i][j]);}printf("\n");}return 0;
}

在这里插入图片描述
但今天小编的主要想法还是带着小伙伴一起用指针数组 来模拟咱们的 二维数组
小伙伴都眼睛睁大咯,可不要眨眼哦 😁 😁 😁

<2>. 模拟二维数组

宝子们请先看代码哦


//指针数组模拟二维数组
#include<stdio.h>int main()
{int a1[5] = {1,2,3,4,5};int a2[5] = {2,3,4,5,6};int a3[5] = {3,4,6,7,8};//将每个一维数组的首地址放入指针数组中int* a[3] = { {a1},{a2},{a3} };int i = 0, j = 0;//先找到第几个 一维数组for (i = 0; i < 3; i++){//再找到该 一维数组中的每一个元素for ( j = 0; j < 5; j++){printf("%d ", a[i][j]);}printf("\n");}return 0;
}

在这里插入图片描述
友友们是不是也都看到了

我们的把每个一维数组的地址都放在指针数组中,通过指针数组的下标 i 我们可以访问 哪个一维数组

再通过该一维数组的下标 j 来访问具体元素,从而达到 二维数组 的效果 。

鱼式疯言

人狠话不多
看图说话
在这里插入图片描述

先走指针,后走一维数组

总结

  • 数组名的含义 :知晓了数组名的一般含义,以及他的两种特殊情况
  • 数组名的实际运用 : 我们通过指针的形式更进一步利用数组名自身含义的特点来输入输出
  • 一维数组传参的本质 : 传参的本质还是数组名的自身含义,以及数组长度如何解决的办法
  • 指针数组 : 我们更了解了指针数组的基本概念
  • 指针数组的实际运用 : 通过我们了解的指针数组的基本概念来对实践我们的理解

如果觉得小编写的还不错的咱可支持三连下 (定有回访哦) , 不妥当的咱请评论区指正

希望我的文章能给各位宝子们带来哪怕一点点的收获就是 小编创作 的最大动力 💖 💖 💖

在这里插入图片描述

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

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

相关文章

正版软件 - Proxyman:让网络调试变得更智能、更高效

在软件开发的世界里&#xff0c;网络调试一直是开发者和测试工程师的痛点。传统的调试工具往往操作复杂&#xff0c;界面不够直观&#xff0c;而且性能上也难以满足现代应用的需求。今天&#xff0c;我要向大家介绍一款名为Proxyman的网络调试工具&#xff0c;它以其简洁的界面…

ssm+vue的医药垃圾分类管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的医药垃圾分类管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

C语言笔试题之两数相加(多次反转链表实现)

实例要求&#xff1a; 1、给定两个非空链表&#xff08;l1和l2&#xff09;来代表两个非负整数&#xff1b;2、数字最高位位于链表开始位置&#xff1b;3、它们的每个节点只存储一位数字&#xff1b;4、将这两数相加会返回一个新的链表&#xff1b; 案例展示&#xff1a; 实例…

MySQL学习记录——칠 表操作

文章目录 1、了解2、创建和插入1、基本创建和插入2、插入并更新on duplicate3、插入并替换replace 3、Retrieve1、查询select2、条件查询where3、结果排序order by4、限制行数limit 4、更新Update5、删除delete6、去重7、聚合函数&#xff08;5个&#xff09;1、count2、sum3、…

【蓝桥杯单片机记录】IO基础与LED控制

目录 一、IO基础 1.1 IAP15F2K61S2芯片原理图 1.2不同工作模式 二、新建工程的一些补充 2.1 keil中没有IAP15F2K61S2的头文件 解决&#xff1a;在isp软件中找到如下​编辑 2.2keil中的芯片选择 2.3推荐字体 三、sbit关键字 四、LED控制 4.1原理图 4.2不能直接通过IO…

Token、Tokenization 和张量之间的关系

输入经过Tokenization、Embedding和Positional Encoding后&#xff0c;最终构建为张量&#xff0c;给后续的计算和处理带来很多优势。 1. tokenization和张量 在自然语言处理&#xff08;NLP&#xff09;领域中&#xff0c;tokenization 是文本预处理的重要步骤之一&#xff0…

【漏洞复现】SpringBlade export-user接口存在SQL注入漏洞

漏洞描述 SpringBlade 是一个由商业级项目升级优化而来的微服务架构 采用Spring Boot 2.7 、Spring Cloud 2021 等核心技术构建,完全遵循阿里巴巴编码规范。提供基于React和Vue的两个前端框架用于快速搭建企业级的SaaS多租户微服务平台。SpringBlade export-user接口存在SQL注…

【踏雪无痕的痕一】——认知的心病

目录 一、背景介绍二、思路&方案三、过程1.教育是最大的"炸片"2.逻辑对等性的认知(时间的保证)3.不要去猜一个人怎么想&#xff0c;要看一个人怎么做4.改变一个人的基础5.你想过和你能过上什么生活完全取决于你自己 四、总结 一、背景介绍 大多数人都只愿意看到…

Blazor Wasm Google 登录

目录: OpenID 与 OAuth2 基础知识Blazor wasm Google 登录Blazor wasm Gitee 码云登录Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务Blazor SSR/WASM IDS/OIDC 单点登录授权实例2-登录信息组件wasmBlazor SSR/WASM IDS/OIDC 单点登录授权实例3-服务端…

给大家拜年啦!最全科研资料,新年促销优惠!机器学习预测全家桶/故障诊断全家桶/改进算法/Python,Matlab代码...

最近后台有不少小伙伴问到&#xff0c;新年有没有什么优惠价&#xff0c;您这也不搞个活动吗&#xff01; 本期作者郑重推出几个比较受欢迎的全家桶&#xff01;一律7折优惠&#xff01;每个商品仅限5次购买机会&#xff0c;也就是说&#xff0c;满5个人后&#xff0c;该商品会…

Stable Diffusion 模型下载:GhostMix(幽灵混合)

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 GhostMix 是绝对让你惊艳的模型&#xff0c;也是自己认为现在最强的2.5D模型。我认为模型的更新应该是基于现有的画面整体不大变的前提下&#xff0c;提高模型的成…

使用Arcgis裁剪

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、掩膜提取二、随意裁剪三、裁剪 前言 因为从网站下载的是全球气候数据&#xff0c;而我们需要截取成中国部分&#xff0c;需要用到Arcgis的裁剪工具 一、掩…

零基础学Python(9)— 流程控制语句(下)

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。流程控制语句是编程语言中用于控制程序执行流程的语句&#xff0c;本节课就带大家认识下Python语言中常见的流程控制语句&#xff01;~&#x1f308; 目录 &#x1f680;1.while循环 &#x1f680;2.for循环 &#x1…

嵌入式中SolidWorks2022 安装教程

软件介绍 SolidWorks是一款专业的三维3D设计软件&#xff0c;功能强悍&#xff0c;支持分布式数据管理&#xff0c;支持直接处理网格数据&#xff0c;提供更多的数据的灵活性&#xff0c;使用起来高效便捷。可以帮助用户轻松进行3D CAD设计、机械设计、钣金设计、模拟设计、电气…

[CUDA手搓]从零开始用C++ CUDA搭建一个卷积神经网络(LeNet),了解神经网络各个层背后算法原理

文章目录 前言一、所需环境二、实现思路2.1. 定义了LeNet网络模型结构&#xff0c;并训练了20次2.2 以txt格式导出训练结果(模型的各个层权重偏置等参数)2.3 (可选)以pth格式导出训练结果&#xff0c;以方便后期调试2.4 C CUDA要做的事 三、C CUDA具体实现3.1 新建.cu文件并填好…

Android SDK 上传 Maven 喂奶级教程

最近领导给安排了个任务&#xff0c;让我把我们现有的一个 SDK 上传到 Maven 上去&#xff0c;方便客户直接用 gradle 依赖&#xff0c;不再需要拷贝 jar 和 so 了&#xff0c;此前我也看过一些相关的文章我想问题也不大&#xff0c;觉得工作量也就一两天的事情&#xff0c;主要…

Peter算法小课堂—枚举优化

哈哈哈&#xff0c;新年快乐&#xff01;这一次Peter将要给大家讲一讲轻松、摆烂的算法—枚举&#xff01;咋就是说呀&#xff0c;枚举这个玩意我语法就会了。但大家想想&#xff0c;咱们CSP考试时&#xff08;除了没过初赛的&#xff09;只给1秒&#xff0c;大家想想&#xff…

STM32Cubmax AD采集

一、基本概念 二、项目 AD函数结构体 typedef struct { uint32_t Mode; // ADC 工作模式选择 FunctionalState ScanConvMode; /* ADC 扫描&#xff08;多通道&#xff09; 或者单次&#xff08;单通道&#xff09;模式选择 */ FunctionalState ContinuousConvMode; // ADC 单…

【深度学习】pytorch 与 PyG 安装(pip安装)

【深度学习】pytorch 与 PyG 安装&#xff08;pip安装&#xff09; 一、PyTorch安装和配置&#xff08;一&#xff09;、安装 CUDA&#xff08;二&#xff09;、安装torch、torchvision、torchaudio三个组件&#xff08;1&#xff09;下载镜像文件&#xff08;2&#xff09;创建…

2024腾讯云游戏服务器租用多少钱一年?

2024年更新腾讯云游戏联机服务器配置价格表&#xff0c;可用于搭建幻兽帕鲁、雾锁王国等游戏服务器&#xff0c;游戏服务器配置可选4核16G12M、8核32G22M、4核32G10M、16核64G35M、4核16G14M等配置&#xff0c;可以选择轻量应用服务器和云服务器CVM内存型MA3或标准型SA2实例&am…