IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C语言】一次让你看透数组的笔试题 -> 正文阅读

[C++知识库]【C语言】一次让你看透数组的笔试题

? ? ? 以下内容含金~

? ? ? ?带你掌握数组名与地址的各种关系,克服畏惧数组的心理?!??


目录

一维数组

解析

字符数组

解析

二维数组

解析


一维数组

? ? ? ? 你能做出几道?证明一下自己的实力?

int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(a[1]));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(*&a));
printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]));
printf("%d\n",sizeof(&a[0]+1));

解析

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

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

数组名一定是首元素地址吗?

提示一点,只有以下两种情况出现数组名才表示整个数组,其他情况一律表示首元素地址
1.sizeof(数组名);
2.&数组名;

所以这里表示整个数组,因而求的是整个数组的大小,也就是4个整形的大小,答案是16

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

注意这里,sizeof()内部数组名没有单独出现,故这里表示首元素的地址,地址的大小是多少呢?

答案是4/8(32位平台/64位平台)

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

首元素地址解引用也就是首元素,是一个整形,所以

答案是4

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

首元素地址+1 = 下一个地址 因为数组中地址是连续的,故指向下一个元素的地址
但他的本质依然是地址哩~ 所以

答案是4/8

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

a[1] == *(a + 1);也就是数组的第二个元素,所以

答案是4

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

注意,这里是取出整个数组的地址,但他终究还是是地址阿~ 所以

答案是4/8

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

打开你的思维
两种理解方式:
1.取出整个数组的地址,再解引用,相当于找到了整个数组,也就是计算整个数组的大小
2.*与&抵消,相当单独将数组名放入sizeof内部

答案是16
printf("%d\n",sizeof(&a+1));

取出整个数组的地址,+1跳过整个数组,但依然是地址,所以

答案是4/8

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

打开你的思维
两种理解方式:
1.a[0]是数组的第一个元素,取出他的地址
2.&a[0] == &*(a + 0); 这里&*抵消,剩下a + 0,也就是首元素的地址

答案是4/8

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

取出数组第一个元素的地址,+1跳过一个元素的地址,指向数组第二个元素的地址,终究还是地址~

答案是4/8

值得注意的是

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

跳过整个数组指的是 由

?到+1后的操作

?


字符数组

????????你能做出几道?证明一下自己的实力?

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));

printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));

printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
char *p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));

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

解析

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));

数组名单独放在sizeof内部,求的是整个数组的大小 所以

答案是6

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

数组名没有单独放在sizeof内部,表示首元素地址,首元素地址+0还是首元素地址 所以

答案是4/8

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

首元素地址解引用,得到首元素,是一个字符'a' 所以

答案是1

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

arr[1]表示数组第二个元素,是字符'b' 所以

答案是1

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

这里取出整个数组的地址,但依旧是地址~ 所以

答案是4/8

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

取出整个数组的地址,+1跳过整个数组,但依旧是地址~ 所以

答案是4/8

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

取出首元素的地址,+1跳过第一个元素,指向数组第二个元素的地址,所以
答案是4/8

------------------------以下是strlen------------------------------

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

将首元素的地址给strlen求字符串长度,到'\0'停止
但是数组中真的有放'\0'吗?
实际上,数组里只存放了abcdef这六个字符
所以strlen会一直找啊找,找啊找,直到找到内存中随机初始化的\0截至

答案是 随机数
printf("%d\n", strlen(arr+0));

首元素地址+0还是首元素地址,数组中没有'\0' 所以

答案是 随机数

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

将首元素放进strlen这算什么呀?
什么都不算,这时一种错误的写法
为什么呢?看一下strlen函数的要求:
size_t strlen( const char *string );
他需要的是一个const的指针

想象一下,将字符'a'强行塞入,经ASCII转换后是97,访问的是97处的地址啊
这是一个位置极低的地址,已经造成了非法访问,如果你有兴趣,编译这段代码
程序走到这里就会挂掉

答案是 error
printf("%d\n", strlen(arr[1]));

这个也是同样的道理,只不过是第二个元素

答案是 error

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

取出整个数组的地址,这可怎么办呢?

大家是否还记得取出首元素的地址和取出整个数组的地址是一样的,因为就算你要一次访问
整个数组,起始位置也一定是首元素地址不是吗?

但闹了半天,却因数组里没有'\0' 所以

答案是 随机数

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

取出整个数组的地址,+1跳过整个数组,但内存中未初始化的位置内容都是随机的 所以

答案是 随机数-6

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

取出首元素的地址,+1指向第二个元素 所以

答案是 随机数-1
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));

这里arr单独出现在sizeof内部,表示计算整个数组的大小,但要注意哦
这里的字符串里隐藏了一个'\0' 所以

答案是7

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

arr没有单独出现在sizeof内部,表示首元素地址 所以

答案是4/8

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

首元素地址解引用得到数组第一个元素,是字符'a' 所以

答案是1

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

arr[1]表示数组的第二个元素,是字符'b' 所以

答案是1

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

取出整个数组的地址,但依然是地址 所以

答案是4/8

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

取出整个数组的地址,+1跳过整个数组,但依然是地址, 所以

答案是4/8

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

取出首元素的地址,+1指向第二个元素,但依然是地址~ 所以
答案是4/8

--------------------以下是strlen----------------------------

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

strlen读到'\0'停止,这里arr表示首元素的地址,表示从首元素开始读取 所以

答案是6

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

首元素地址+0还是首元素地址 所以

答案是6

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

首元素地址解引用放入strlen,上面的题解释过,造成了非法访问,这是一种错误写法,所以

答案是error

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

arr[1]是首元素和上一题同理 所以

答案是error

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

取出整个数组的地址,整个数组的地址也是从首元素地址开始访问 所以

答案是6

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

取出整个数组的地址,+1跳过整个数组,相当与也跳过了数组结尾的'\0' 所以

答案是 随机数

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

取出首元素的地址,+1指向数组第二个元素 所以

答案是5
char *p = "abcdef";
printf("%d\n", sizeof(p));

char*类型的p能存放的了这个字符串吗?
当然不行(具体在指针进阶文章里有讲)
这里存放的首元素a的地址 所以

答案是4/8

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

p是首元素的地址,首元素地址+1指向下一个元素的地址,但还是地址~ 所以

答案是4/8

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

首元素地址解引用找到字符'a' 所以

答案是1

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

p[0] == *(p + 0);表示第一个元素 所以

答案是1

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

p表示首元素地址,&p表示取出首元素地址的地址,相当于一个二级指针,但还是地址~ 所以

答案是4/8

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

取出首元素地址的地址,+1跳过p这块空间的地址(此处一会画图解释),但还是地址~ 所以

答案是4/8

printf("%d\n", sizeof(&p[0]+1));
取出首元素的地址,+1跳过第一个元素的地址,指向第二个元素地址,但还是地址~ 所以
答案是4/8

---------------------------以下是strlen-----------------------------------

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

p是首元素地址,strlen计算字符串长度到'\0'停止 所以

答案是6

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

首元素地址+1,指向下一个元素的地址 所以

答案是5

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

首元素地址解引用,得到的是首元素,是一个字符'a',和之前的一道题一样,非法访问内存空间 所以

答案是error

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

和上一题同理 所以

答案是error

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

p表示首元素地址,&p表示取出首元素地址的地址,但后面内容是随机初始化(一会画图解释) 所以

答案是 随机值

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

和上一道题同理,&p+1只是跳过了这个p的地址,后面内容随机初始化 所以

答案是 随机数

printf("%d\n", strlen(&p[0]+1));
取出首元素的地址,+1指向第二个元素的地址,所以

答案是5

对于

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

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

p这个指针变量与"abcdef"的存储位置是不一样的

p是一个局部变量,在栈区上开辟空间,而常量字符串"abcdef"是在静态区开辟的空间

如图:

?+1跳过的是什么呢

如图

?想必这时大家心里因该很清楚啦。


二维数组

????????你能做出几道?证明一下自己的实力?

int a[3][4] = {0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*(a[0]+1)));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));

解析

int a[3][4] = {0};
printf("%d\n",sizeof(a));

数组名单独放在sizeof内部,表示计算整个数组大小,也就是12个整形大小 所以

答案是48

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

a[0][0] == *(*(a + 0) + 0); 就是第一行第一个元素 所以

答案是4

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

a[0] == *(a + 0);这里a表示数组第一行的地址,+0还是第一行,解引用相当于拿到
第一行的数组名,将第一行的数组名单独放入sizeof内部,相当于计算第一行的大小,
(这里这一类比一维数组) 所以

答案是4

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

与上一道题同理,a[0]拿到第一行的数组名,数组名没有单独放在sizeof内部表示
第一行的首元素地址,第一行首元素的地址+1,指向第一行第二个元素的地址,但还是地址 所以

答案是4/8

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

与上一道题同理a[0]+1表示第一行第二个元素的地址,解引用相当于找到了第一行第二个元素,是个整形

答案是4

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

a表示首元素地址,+1跳过第一行的地址,指向第二行的地址,但还是地址~

答案是4/8

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

与上一题同理,a+1表示第二行地址,第二行的地址解引用相当于找到了第二行的数组名,第二行
数组名单独放入sizeof内部表示计算第二行的数组大小 所以

答案是16

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

a[0]表示一行的数组名,&a[0]表示取出第一行数组名的地址,+1指向第二行的数组名的地址 所以

答案是4/8

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

与上一题同理,&a[0]+1表示第二行的地址,解引用相当于找到了第二行的数组名,数组名单独放入sizeof
内部,表示计算第二行的大小

答案是16

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

a没有单独放入sizeof内部表示第一行的地址,第一行的地址解引用拿到第一行的数组名,第一行的
数组名单独放入sizeof计算数组第一行的大小 所以

答案是16

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

这道题很有意思
可能有的就要说了,这一看就是错的呀,越界访问了~
但其实你可能忘了一点
sizeof只关心的是类型,而非内容
你是否有见过这种写法sizeof(int)
起始就是在计算int的大小,包括平时写int a = 5; sizeof(a);
这也是在计算a这个类型的大小
这道题a[3]就是拿到第四行的数组名,数组名单独放入sizeof内部表示计算数组第四行的大小 所以

答案是16

? ? ? ?


不断揭示数组名的意义本质

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

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

3. 除此之外所有的数组名都表示首元素的地址。

码字不易~

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-05 23:22:06  更:2022-07-05 23:24:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/11 17:28:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码