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

2024-03-10 21:52
文章标签 理解 一篇 就够 数组名

本文主要是介绍数组名的理解,看这一篇就够了!!!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

一:数组名的理解:

数组名是数组首元素的地址,但是有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.chinasem.cn/article/795643

相关文章

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

深入理解Redis大key的危害及解决方案

《深入理解Redis大key的危害及解决方案》本文主要介绍了深入理解Redis大key的危害及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、背景二、什么是大key三、大key评价标准四、大key 产生的原因与场景五、大key影响与危

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分