【C语言】一次让你看透数组的笔试题

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 【C语言】一次让你看透数组的笔试题,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

      以下内容含金~

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


目录

一维数组

解析

字符数组

解析

二维数组

解析


一维数组

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

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

跳过整个数组指的是 由

【C语言】一次让你看透数组的笔试题

 到+1后的操作

【C语言】一次让你看透数组的笔试题

 


字符数组

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

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”是在静态区开辟的空间

如图:

【C语言】一次让你看透数组的笔试题

 +1跳过的是什么呢

如图

【C语言】一次让你看透数组的笔试题

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


二维数组

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

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. 除此之外所有的数组名都表示首元素的地址。

码字不易~

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/129919.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!