数组名的理解,看这一篇就够了!!!

news2024/11/17 10:44:28

!!!以下是会涉及到的知识的讲解:

一:数组名的理解:

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

1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。

2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址

除了这两点以外,以外的数组名都是数组首元素的地址!!

二:两个理解(sizeof和strlen)

1、用法不一样

sizeof可以用类型(指针,整形等等)做参数,也可以用数组做参数。

strlen只能用char*做参数,且必须是以''\0''结尾的,才能计算出准确的值,否则,是随机值;另外strlen的参数不能是指针以外的类型(比如整形),否则结果为error(错误)。

2、功能不一样

sizeof的功能能是,获得保证,能容纳实现所建立的最大对象的字节大小。

strlen的功能是返回字符串的长度,该字符串可能是自己定义的,也可能是内存中随机的,该函数实际完成的功能是从代表该字符串的第一个地址开始遍历,直到遇到结束符 \0 。返回的长度大小不包括 \0 。

3、意思不一样

sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组、指针、类型、对象、函数等。

strlen(...)是函数,要在运行时才能计算。参数必须是字符型指针(char*)。当数组名作为参数传入时,实际上数组就退化成指针了。

!!!题目讲解:各种数组和sizeof或strlen的结合

 一:

第一种:sizeof+整形一维数组

 1,printf("%d\n", sizeof(arr)); 

  数组名单独放在sizeof内部,这里的a表示整个数组,计算的是整个数组的大小,单位是字节,总共16个字节。

2,printf("%d\n", sizeof(a+0));

  因为数组名没有单独放在sizeof内部,所以a表示数组首元素的地址,a+0还是数组首元素的地址,是地址,大小就是4/8个字节。

3,printf("%d\n", sizeof(*a));

  a在这里表示数组首元素的地址,*a就是首元素,大小4个字节

4,printf("%d\n", sizeof(a+1));

  数组名a在这里是数组首元素的地址,a+1是第二个元素的地址,地址的大小为4/8。

5,printf("%d\n", sizeof( a[1] ));

  第二个元素的大小就是4个字节

6,printf("%d\n",sizeof(&a));

  &a是整个数组的地址,但是整个数组的地址也是地址,所以大小4/8。

7, printf ( "%d\n" , sizeof ( *& a ));
  sizeof(*&a)中,*&抵消,所以就是sizeof(a),数组名单独放在sizeof内部,这里的a表示整个数组,所以16。(虽然不是sizeof(数组名),但是*&抵消就是了)

8,printf("%d\n",sizeof(&a+1));

  &a+1,相对于&a的地址去跳过了整个数组,但是即使跳过了整个数组,&a+1依然是地址,是地址就是4/8个字节。

9,printf("%d\n",sizeof(&a[0]));

  &a[0]是取出了首元素的地址,是地址大小就是4/8个字节。

10,printf("%d\n",sizeof(&a[0]+1));

  &a[0]是首元素的地址,&a[0]+1就是第二个元素的地址,是地址大小就是4/8。

代码注释:

二: 

第二种:sizeof+字符数组(字符数组不含\0,除非有一个字符为\0)

 1,printf("%d\n", sizeof(arr));

  数组名单独放在sizeof内部,这里的arr表示整个数组,计算的是整个数组的大小,单位是字节,总共6个字节

2,printf("%d\n", sizeof(arr + 0));

 因为数组名没有单独放在sizeof内部,所以arr表示数组首元素的地址,arr+0还是数组首元素的地址,是地址就是4/8个字节

3,printf("%d\n", sizeof(*arr));

  arr表示数组首元素的地址,*arr就是首元素,首元素是'a',大小1个字节

4,printf("%d\n", sizeof(arr[1]));

  arr[1]就是第二个元素'b',大小是1个字节

5,printf("%d\n", sizeof(&arr));

  &arr是数组的地址,但是数组的地址也是地址,是地址就是4/8

6,printf("%d\n", sizeof(&arr + 1));

  &arr + 1是跳过整个数组后的地址,是地址就是4/8个字节

7,printf("%d\n", sizeof(&arr[0] + 1));

  &arr[0]是取出第一个元素的地址,然后+1是第二个元素的地址,是地址大小就是4/8个字节

代码注释:

三: 

第三种:strlen+字符数组(字符数组不含\0,除非有一个字符为\0 )

1,printf("%d\n", strlen(arr));

  随机值,因为字符数组arr中没有\0,arr是首元素地址,所以在求字符串长度的时候,会一直往后找,产生的结构就是随机值

2,printf("%d\n", strlen(arr + 0));

  随机值,arr + 0是首元素的地址,和第一个一样,也是随机值

3,printf("%d\n", strlen(*arr));

  error, arr是数组首元素的地址,*arr就是数组首元素,就是'a'-97,strlen函数参数的部分需要传一个地址,当我们传递的是'a'时,'a'的ASCII码值是97,那就是将97作为地址传参,strlen就会从97这个地址开始统计字符串长度,这就非法访问内存了

4,printf("%d\n", strlen(arr[1]));

  error,因为arr[1]也是数组首元素,所以与3一致

5,printf("%d\n", strlen(&arr));

  随机值,&arr是数组的地址,数组的地址和数组首元素的地址,值是一样的,那么传递给strlen函数后,依然是从数组的第一个元素的位置开始往后统计,所以也是随机值

6,printf("%d\n", strlen(&arr + 1));

  随机值,&arr + 1代表越过了整个数组后的地址,所以也是随机值,不知道什么时候才能碰上 \0 

7,printf("%d\n", strlen(&arr[0] + 1));

  &arr[0] + 1是第二个元素的地址,结果也是随机值

代码注释:

四:

第四种:sizeof+字符 串 数组(字符串末尾会自带 \0 )

1,printf("%d\n", sizeof(arr));

  7,因为除开6个元素,\0 也会记入,总计7个元素,每个大小为1个字节

2,printf("%d\n", sizeof(arr + 0));

  arr + 0是首元素的地址 ,是地址所以大小4/8

3,printf("%d\n", sizeof(*arr));

  *arr其实就是首元素,1个字节,所以1,可以理解为*arr--> *(arr+0) -- arr[0]

4,printf("%d\n", sizeof(arr[1]));

  arr[1]是第二个元素,1个字节大小,所以1

5,printf("%d\n", sizeof(&arr));

  &arr虽然是整个数组的地址,但是地址就是4/8个字节

6,printf("%d\n", sizeof(&arr + 1));

  &arr + 1是跳过整个数组的地址,但也是地址,所以是4/8

7,printf("%d\n", sizeof(&arr[0] + 1));

  &arr[0] + 1是第二个元素的地址,是地址大小就是 4/8

代码注释:

五:

第五种:strlen+字符 串 数组(字符串末尾会自带 \0)

1,printf("%d\n", strlen(arr));

  6,因为返回的长度大小不包括 \0 

2,printf("%d\n", strlen(arr + 0));

  6,因为arr+0和arr一样,都是首元素地址。

3,printf("%d\n", strlen(*arr));

  err,因为,strlen的参数不能是指针以外的类型(比如整形,char型),否则结果为error,而*arr是首元素。

4,printf("%d\n", strlen(arr[1]));

  err,因为,strlen的参数不能是指针以外的类型(比如整形,char型),否则结果为error,而arr[1]是第二个元素。

5,printf("%d\n", strlen(&arr));

  6,&arr是整个数组的首地址,对于strlen来说该字符数组的首地址。

6,printf("%d\n", strlen(&arr + 1));

  随机值,因为&arr + 1,这个指针跳过了整个数组,数组以外往后去寻找,不知道什么时候才能找到\0。

7,printf("%d\n", strlen(&arr[0] + 1));

  5,因为&arr[0] + 1是第二个元素的首地址,往后寻找到 \0 刚好5个元素。

代码注释

六:

第六种:sizeof+赋给字符指针的字符串(字符串末尾自带 \0)

char * p="abcdef" 相当于把字符串abcdef的首地址给p了,并不是把"abcdef"放进了p里面

1,printf("%d\n", sizeof(p));

  p是一个指针,所以大小就是4/8

2,printf("%d\n", sizeof(p + 1));

  p+1是'b'的地址,是地址大小就是4/8个字节

3,printf("%d\n", sizeof(*p));

  *p 就是'a',就是1个字节

4,printf("%d\n", sizeof(p[0]));

  p[0]--> *(p+0) --> *p ,就是'a',所以1个字节

5,printf("%d\n", sizeof(&p));

  4/8,&p -- char**,是存放指针p的指针,是地址就是4/8

6,printf("%d\n", sizeof(&p + 1));

  4/8,&p + 1,代表第二个元素的地址,,是地址大小就为4/8

7,printf("%d\n", sizeof(&p[0] + 1));

  4/8 , &p[0] + 1得到是'b'的地址,是地址大小就是4/8

代码注释:

七:

第七种:strlen+赋给字符指针的字符串(字符串末尾自带 \0)

char * p="abcdef" 相当于把字符串abcdef的首地址给p了,并不是把"abcdef"放进了p里面

1,printf("%d\n", strlen(p));

  6,第一个元素开始寻找 \0

2,printf("%d\n", strlen(p + 1));

  5,第二个元素开始寻找 \0

3,printf("%d\n", strlen(*p));

  error,*p是元素,是'a',strlen的参数不能是指针以外的类型(比如整形,char型),否则结果为error

4,printf("%d\n", strlen(p[0]));

  error,p[0]是元素,是'a',strlen的参数不能是指针以外的类型(比如整形,char型),否则结果为error

5,printf("%d\n", strlen(&p));

  随机值,因为&p是存放p这个指针的指针,已经和原来的字符串无关了,我们不知道这个二级指针里面的东西,以及会什么时候遇到 \0

6,printf("%d\n", strlen(&p + 1));

  随机值,因为&p + 1 是存放p这个指针的指针+1,已经和原来的字符串无关了,我们不知道这个二级指针里面的东西,以及会什么时候遇到 \0

7,printf("%d\n", strlen(&p[0] + 1));

  5,第二个元素开始寻找 \0

八:

第八种:sizeof+二维整形数组

        对于二维数组我们要知道,二维数组是一个存放一维数组的数组,将其中的每个一维数组看成一个元素,这样二维数组就可以看成一维数组了,所以对于a[3][4]来说,a就是数组名,其代表首元素的地址,这个时候首元素为第一行数组(也就是一个一维数组),a+1-1,会以一行为单位

        a[0]是这个一维数组的数组名,该数组名当单独放在sizeof中(sizeof(a[0])),或者前面&的时候(&a[0]),满足那两个条件,其所指的整个数组是它所对应的那一行数组,比如a[0]这个时候就代表第一行数组,a[1]这个时候就代表第二行数组.......现在对其进行+1-1,会以一行数组作为单位来跨越。

1,printf("%d\n", sizeof(a));

  3*4*4 = 48,所有元素的大小总和

2,printf("%d\n", sizeof(a[0][0]));

  4,第一行第一列的元素的大小

3,printf("%d\n", sizeof(a[0]));

  a[0]是第一行这个一维数组的数组名,数组名算是单独放在sizeof内部了,计算的是整个数组的大小,大小是16个字节

4,printf("%d\n", sizeof(a[0] + 1));

  a[0]作为第一行的数组名,没有单独放在sizeo内部,没有&,a[0]表示数组首元素的地址,也就是a[0][0]的地址,所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节

5,printf("%d\n", sizeof(*(a[0] + 1)))

  4,就是在第四问的基础上加上*进行了解引用,计算的是就是第一行第2个元素的大小

6,printf("%d\n", sizeof(a + 1));

  4 / 8,a是数组首元素的地址,是第一行的地址 int(*)[4],a+1 就是第二行的地址,是地址大小就是4/8

7,printf("%d\n", sizeof(*(a + 1)));

  16,*(a+1) --> a[1] -> sizeof(*(a+1))->sizeof(a[1]) 计算的是第二行的大小,a+1 --> 是第二行的地址,int(*)[4],*(a+1) 就是解引用之后访问的第二行的数组

8,printf("%d\n", sizeof(&a[0] + 1));

  4/8,&a[0]是第一行的地址 (类型为int(*)[4]),&a[0]+1 是第二行的地址(类型为 int(*)[4]),是地址大小就是4/8

9,printf("%d\n", sizeof(*(&a[0] + 1)));

  16 计算的是第二行的大小,与第8问类似,不过进行了*解引用,对类型为int(*)[4]的解引用,应该得到4个整形的大小总和

10,printf("%d\n", sizeof(*a));

  16,计算的是第一行的大小,因为a就是数组名,其代表首元素的地址,这个时候首元素为第一行数组,对类型为int(*)[4]的解引用,应该得到4个整形的大小总和,*a --> *(a+0) --> a[0]

11,printf("%d\n", sizeof(a[3]));

  16,a[3]--> int [4],a[3]是第四行数组的首地址,虽然越界了,但是正如文中最上面知识点所说:其值在编译时即计算好了,sizeof只会在乎你的类型,然后知道了你的个数就行。

代码注释:

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

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

相关文章

LeetCode59:螺旋矩阵Ⅱ

题目描述 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n 3 输出:[[1,2,3],[8,9,4],[7,6,5]] 代码 class Solution { public:vector…

查看pip当前关联python版本及位置

好久没用python了,把各种pip指向的环境忘光光啦,这里记录一下查看pip当前关联的python版本及位置的方法: pip -V结果: 我一般不用这个版本的python,去环境变量看了一下,原来是anaconda的Scripts自带pip&a…

Vue class和style绑定:动态美化你的组件

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

EB tersos 24.0.1 添加MCU模块失败

1、问题: 新建工程,添加MCU模块总是失败,错误信息如下: 2、解决方案 创建工程时只保留Resource模块,直接点击Finish,其他模块之后再添加 在工程创建成功后再单独添加需要的模块

StableDiffusion3 官方blog论文研究

博客源地址:Stable Diffusion 3: Research Paper — Stability AI 论文源地址:https://arxiv.org/pdf/2403.03206.pdf Stability.AI 官方发布了Stable diffusion 3.0的论文研究,不过目前大家都沉浸在SORA带来的震撼中,所以这个水…

力扣530. 二叉搜索树的最小绝对差

思路1&#xff1a;中序遍历&#xff0c;递归排序成有序数组&#xff1b;因为是有序&#xff0c;只需要求相邻两个值的最小差值。 class Solution {ArrayList <Integer> list new ArrayList();int ans 100001;//题目最大 100000public int getMinimumDifference(TreeNo…

docker学习笔记——Dockerfile

Dockerfile是一个镜像描述文件&#xff0c;通过Dockerfile文件可以构建一个属于自己的镜像。 如何通过Dockerfile构建自己的镜像&#xff1a; 在指定位置创建一个Dockerfile文件&#xff0c;在文件中编写Dockerfile相关语法。 构建镜像&#xff0c;docker build -t aa:1.0 .(指…

异步编程实战:使用C#实现FTP文件下载及超时控制

博客标题: 异步编程实战&#xff1a;使用C#实现FTP文件下载及超时控制 如果你的函数不是async&#xff0c;你仍然可以实现相同的超时功能&#xff0c;但你将不得不依赖更多的同步代码或使用.Result或.GetAwaiter().GetResult()来阻塞等待任务完成&#xff0c;这可能导致死锁的风…

Breach-2.1

靶场环境说明 该靶场是静态IP地址&#xff0c;需要更改网络配置&#xff0c;攻击机kali做了两张网卡&#xff1b; 信息收集 # nmap -sT --min-rate 10000 -p- 192.168.110.151 -oN port.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-09 10:47 CST Stats: 0:00:…

java通过poi-tl生成word

我看公司之前做电子合同&#xff0c;使用TIBCO jaspersoft做的报表模板&#xff0c;如果是给自己公司开发或者给客户做项目&#xff0c;这个也没有什么&#xff0c;因为反正模板是固定的&#xff0c;一次性开发&#xff0c;不用担心后续的问题。即使后期有调整&#xff0c;改一…

深入解读 Elasticsearch 磁盘水位设置

本文将带你通过查看 Elasticsearch 源码来了解磁盘使用阈值在达到每个阶段的处理情况。 跳转文章末尾获取答案 环境 本文使用 Macos 系统测试&#xff0c;512M 的磁盘&#xff0c;目前剩余空间还有 60G 左右&#xff0c;所以按照 Elasticsearch 的设定&#xff0c;ES 中分片应…

总结:Spring创建Bean循环依赖问题与@Lazy注解使用详解

总结&#xff1a;Spring创建Bean循环依赖问题与Lazy注解使用详解 一前提知识储备&#xff1a;1.Spring Bean生命周期机制&#xff08;IOC&#xff09;2.Spring依赖注入机制&#xff08;DI&#xff09;&#xff08;1&#xff09;Autowired注解标注属性set方法注入&#xff08;2&…

面具安装LSP模块时提示 Unzip error错误的解决办法

面具(Magisk Delta)安装LSP模块时提示 Unzip error错误的解决办法 ​​ 如果前面的配置都正常的话&#xff0c;可能是LSP版本有问题重新去Github下载一个最新版的吧&#xff1b;我是这么解决的。 我安装1.91那个版本的LSP就是死活安装不上&#xff0c;下载了1.92的版本一次就…

Golang-channel合集——源码阅读、工作流程、实现原理、已关闭channel收发操作、优雅的关闭等面试常见问题。

前言 面试被问到好几次“channel是如何实现的”&#xff0c;我只会说“啊&#xff0c;就一块内存空间传递数据呗”…所以这篇文章来深入学习一下Channel相关。从源码开始学习其组成、工作流程及一些常见考点。 NO&#xff01;共享内存 Golang的并发哲学是“要通过共享内存的…

⭐每天一道leetcode:83.删除排序链表中的重复元素(简单;链表遍历、删除经典题目)

⭐今日份题目 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 示例1 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2] 示例2 输入&#xff1a;head [1,1,2,3,3] 输出&#xff1a;[1,2,3] …

Linux 进程程序替换

&#x1f493;博主CSDN主页:麻辣韭菜-CSDN博客&#x1f493;   ⏩专栏分类&#xff1a;http://t.csdnimg.cn/G90eI⏪   &#x1f69a;代码仓库:Linux: Linux日常代码练习&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Linux知识   &#x1f51d;&#x1f5…

考研经验|如何从考研失败中走出来?

对我来说&#xff0c;太丢人了 其实我在本科的时候在同学眼中&#xff0c;一直很优秀&#xff0c;每年奖学金必有我的&#xff0c;国家励志奖学金&#xff0c;国家奖学金&#xff0c;这种非常难拿的奖学金&#xff0c;我也拿过&#xff0c;本科期间学校有一个公费去新西兰留学的…

美化console

console简介 控制台&#xff08;Console&#xff09;是JS开发里最重要的面板&#xff0c;主要作用是显示网页加载过程中产生各类信息,我们经常使用console.log()这个函数在控制台打印一些东西 但是,console这个对象不仅仅有log这个函数,还有很多其他的函数,如下 console.de…

vue学习笔记22-组件传递多种数据类型props效验

组件传递多种数据类型 通过props传递数据&#xff0c;不仅可以传递字符串类型的数据&#xff0c;还可以是其他类型&#xff0c;例如&#xff1a;数字、对象、数组等&#xff0c;但实际上任何类型的值都可以作为props的值被传递&#xff08;即组件与组件之间的传递是没有限制的…

Text Field文本输入框

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Text Field文本输入框 一、最基本的本文输入框1、基础示例2、一些表单属性3、验证 二、多行文本 一、最基本的本文输入框 1、基础示例 import {Box, TextField} from "…