【C语言】指针和数组笔试题解析(1)

指针是C语言的灵魂,他的玩法多种多样,这篇文章带来指针的笔试题详解,可以帮助我们更好的理解与巩固指针的知识


题目比较多,但切记戒骄戒躁,保持空杯心态,相信看完一定会有提升
开始之前要先来一点预备知识:

预备知识:

数组名:

数组名大部分情况下是首元素地址,但有两种情况例外
1.当sizeof(数组名),此时数组名代表整个数组,求出的是整个数组的大小,单位是字节。
2.当&数组名,此时数组名代表整个数组,取出的是整个数组的地址,虽然与首元素地址相同,但含义不一样。

sizeof:

sizeof是一个操作符,可以求变量(类型)所占空间的大小。

strlen:

strlen是一个为库函数,可以获取字符串\0之前的长度

一一一一一一一一一分割线一一一一一一一一一一

题目:

分为两部分,第一部分时一维数组,第二部分是二维数组,逐步攀升难度

假设都在32位机器下进行

一维数组:

第一组:

//一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));//1
printf("%d\n",sizeof(a+0));//2
printf("%d\n",sizeof(*a));//3
printf("%d\n",sizeof(a+1));//4
printf("%d\n",sizeof(a[1]));//5
printf("%d\n",sizeof(&a));//6
printf("%d\n",sizeof(*&a));//7
printf("%d\n",sizeof(&a+1));//8
printf("%d\n",sizeof(&a[0]));//9
printf("%d\n",sizeof(&a[0]+1));//10

答案:

1.16
a代表整个数组,每个数组元素是int类型,一共4个元素,故为16字节大小
2.4
a为首元素地址,当地址进行±运算时,与指针类型有关,a的类型为int*,所以+0时,地址会向前跳过0个整形,仍旧是首元素地址
3.4
a为首元素地址,当解引用时,得到的是arr[0],也就是第一个整形元素,大小为4
4.4
a为首元素地址,当地址进行±运算时,与指针类型有关,a的类型为int*,所以+1时,地址会向前跳过1个整形,而数组是连续存放的,故地址会指向第二个数组元素。
5.4
a[1]是一个整形,为数组第二个整形元素,大小是4字节
6.4
&数组名代表的是取出整个元素的地址,但不管是什么地址,在32位下地址都是4个字节大小
7.16

此题有两种解法:
1.*与&结合会相互抵消,数组名在sizeof中就是求出整个数组的大小
2.&数组名取出的是整个数组的地址,当地址进行解引用时,与指针类型有关,解引用一个数组指针类型的内容,就会访问一个大小为此数组的内容,即4个整形变量的数组,大小为16字节

8.4
a代表整个数组,当地址进行±运算时,与指针类型有关,而此数组指针的类型是 int(*)[4], 数组指针+1会跳过一个数组,也就是跳过4个整形的数组,而运算后的结果仍旧是地址,故答案为4
9.4
&a[0]代表的是第一个元素的地址,地址大小为4字节
10.4
&a[0]代表的是第一个元素的地址,当地址进行±运算时,与指针类型有关,整形指针+1会跳过一个整形,即&a[0]+1指向数组第二个元素,为第二个元素的地址,大小为4个字节

一一一一一一一一一分割线一一一一一一一一一一
第二组:

//字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//1
printf("%d\n", sizeof(arr+0));//2
printf("%d\n", sizeof(*arr));//3
printf("%d\n", sizeof(arr[1]));//4
printf("%d\n", sizeof(&arr));//5
printf("%d\n", sizeof(&arr+1));//6
printf("%d\n", sizeof(&arr[0]+1));//7

答案:
1.6
arr在sizeof中为整个数组,求出的是整个数组的大小,单位是字节,结果为6字节
2.4
arr此时为首元素地址,类型为char*,字符指针+0会跳过0个字符大小,此时仍指向首元素地址,地址大小为4字节
3.1
arr此时为首元素地址,类型为char*,解引用arr会访问一个char大小的内容,为数组第一个元素,大小为1字节
4.1
arr[1]代表数组第二个元素,类型为char,大小为1字节
5.4
arr代表整个数组,取出的是整个数组的地址,地址的大小为4字节
6.4
arr代表整个数组,取出的是整个数组的地址,当地址进行±运算时,与指针类型有关,数组指针的类型为 char (*)[6] ,数组指针+1会跳过一个数组,在这就是跳过6个字符,运算后的结果依然是地址,大小为4
7.4
&arr[0]代表第一个元素的地址,当地址进行±运算时,与指针类型有关,字符指针+1会跳过一个字符,&arr[0]+1代表第二个元素地址,大小为4字节
一一一一一一一一一分割线一一一一一一一一一一
第三组:

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", strlen(arr));//1
printf("%d\n", strlen(arr+0));//2
printf("%d\n", strlen(*arr));//3
printf("%d\n", strlen(arr[1]));//4
printf("%d\n", strlen(&arr));///5
printf("%d\n", strlen(&arr+1));//6
printf("%d\n", strlen(&arr[0]+1));//7

答案:
1.随机值
arr为首元素地址,但arr数组中没有’\0’,故结果为随机值
2.随机值
arr为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+0会向前跳过0个字符,地址不变,而arr数组中没有’\0’,故结果为随机值
3.err
arr为首元素地址,*arr为第一个元素’a’,传入strlen中会把a的ASCII码值当做地址,而此地址为野指针,会报错。
4.err
arr[1]为数组第二个元素’b’,传入strlen中会把b的ASCII码值当做地址,而此地址为野指针,会报错。
5.随机值
arr为整个数组地址,首先要知道strlen的参数为在这里插入图片描述
传入strlen后数组指针会被强转为char *类型,而他们两的值是一样的,故结果为随机值
6.随机值
arr为整个数组地址,当地址进行±运算时,与指针类型有关,数组指针+1会向前跳过一个数组,故此时地址为跳过一个数组的地址,由于不清楚什么时候遇到’\0’,故为随机值
7.随机值
&arr[0]为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+1会向前跳过一个字符,故此时地址为跳过一个字符的地址,由于不清楚什么时候遇到’\0’,故为随机值
一一一一一一一一一分割线一一一一一一一一一一
第四组:

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

答案:
1.7
arr代表整个数组,在sizeof中会求出整个数组的大小,为7字节,因为写成字符串形式自带’\0’
2.4
arr为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+1会向前跳过1个字符,故此时地址为跳过一个字符的地址,则结果为4
3.1
arr为首元素地址,类型为char* ,解引用时会访问一个字节,为’a’,字符a的大小为1的字节
4.1
arr[1]为数组中第二个元素的地址,为char类型,大小为1字节
5.4
arr为整个数组地址,&arr为整个元素的地址,是地址就是4个字节
6.4
arr为整个数组地址,&arr为整个元素的地址,类型为char(*)[7],数组指针+1会跳过1个数组,&arr+1为跳过一个数组后的地址,是地址大小就是4字节
7.4
&arr[0]为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+1会向前跳过1个字符,故此时地址为跳过一个字符的地址,则结果为4
一一一一一一一一一分割线一一一一一一一一一一
第五组:

char arr[] = "abcdef";
printf("%d\n", strlen(arr));//1
printf("%d\n", strlen(arr+0));//2
printf("%d\n", strlen(*arr));//3
printf("%d\n", strlen(arr[1]));//4
printf("%d\n", strlen(&arr));//5
printf("%d\n", strlen(&arr+1));//6
printf("%d\n", strlen(&arr[0]+1));//7

答案:
1.6
arr为首元素地址,因为字符串自带\0,故传入首元素地址后会得到\0之前的字符串个数,也就是6
2.6
arr为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+0会向前跳过0个字节,故传入首元素地址后会得到\0之前的字符串个数,也就是6
3.err
arr为首元素地址,解引用后得到字符a,会将字符a的ASCII码值当做地址传入strlen,由于此地址为野指针,故会error
4.err
arr[1]为字符b,会将字符b的ASCII码值当做地址传入strlen,由于此地址为野指针,故会error
5.6
arr为整个数组地址,&arr为整个元素的地址,传入strlen后数组指针会被强转为char *类型,而他们两的值是一样的,故结果为6

6.随机值
arr为整个数组地址,&arr为整个元素的地址,类型为char(*)[7],数组指针+1会跳过1个数组,&arr+1为跳过一个数组后的地址,传入strlen后数组指针会被强转为字符指针类型
7.5
arr[0]为数组首元素,&arr[0]为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+1会向前跳过1个字符,故得到的结果为5
一一一一一一一一一分割线一一一一一一一一一一
第六组:

char *p = "abcdef";
printf("%d\n", sizeof(p));//1
printf("%d\n", sizeof(p+1));//2
printf("%d\n", sizeof(*p));//3
printf("%d\n", sizeof(p[0]));//4
printf("%d\n", sizeof(&p));//5
printf("%d\n", sizeof(&p+1));//6
printf("%d\n", sizeof(&p[0]+1));//7

答案:
1.4
p为字符指针,是指针大小就为4字节
2.4
p+1指向数组第二个元素,但仍旧是地址,是地址就是4字节
3.1
p为字符首元素地址,解引用得到首元素,类型是char,故大小为1字节
4.1
p[0]可以写成*(p+0),也就是数组第一个元素,类型是char,大小是1字节
5.4
&p是字符指针的地址,是地址大小就为4字节
6.4
&p是地址的地址,当地址进行±运算时,与指针类型有关,&p的类型为char**,+1会跳过一个char*类型的,但仍旧是地址,为4字节
7.4
&p[0]为首元素地址,类型是字符指针,+1会跳过一个字节,但仍旧是地址,为4字节
一一一一一一一一一分割线一一一一一一一一一一
第七组:

char *p = "abcdef";
printf("%d\n", strlen(p));//1
printf("%d\n", strlen(p+1));//2
printf("%d\n", strlen(*p));//3
printf("%d\n", strlen(p[0]));//4
printf("%d\n", strlen(&p));//5
printf("%d\n", strlen(&p+1));//6
printf("%d\n", strlen(&p[0]+1));//7

答案:
1.6
p为字符串的首元素地址,传入strlen中得到6
2.5
p为字符串首元素地址,当地址进行±运算时,与指针类型有关,字符指针会跳过一个字节指向b,将b的地址传入strlen中得到5
3.err
p为字符首元素地址,解引用得到首元素,会将字符a的ASCII码值当做地址传入strlen,由于此地址为野指针,故会error
4.err
p[0]为字符a,会将字符a的ASCII码值当做地址传入strlen,由于此地址为野指针,故会error
5.随机值
&p得到的是字符指针的地址,由于不知道何时出现\0,故为随机值
6.随机值
&p是地址的地址,当地址进行±运算时,与指针类型有关,&p的类型为char**,+1会跳过一个char*类型的,由于不知道何时出现\0,故为随机值
7.5
&p[0]为首元素地址,类型是字符指针,+1会跳过一个字节,故得到5

二维数组:

int a[3][4] = {0};
printf("%d\n",sizeof(a));//1
printf("%d\n",sizeof(a[0][0]));//2
printf("%d\n",sizeof(a[0]));//3
printf("%d\n",sizeof(a[0]+1));///4
printf("%d\n",sizeof(*(a[0]+1)));//5
printf("%d\n",sizeof(a+1));//6
printf("%d\n",sizeof(*(a+1)));//7
printf("%d\n",sizeof(&a[0]+1));//8
printf("%d\n",sizeof(*(&a[0]+1)));//9
printf("%d\n",sizeof(*a));//10
printf("%d\n",sizeof(a[3]));//11

开始之前要明确几个概念:
二维数组是数组的数组
每一行的数组名是a[0],a[1],a[2]
在这里插入图片描述

答案:
1.48
a是二维数组的数组名,在sizeof中表示整个数组,那么得到的结果就是整个数组的大小,为48字节
2.4
a[0][0]为第一个元素,类型是int,故大小为4字节
3.16
a[0]是第一行的数组名,数组名放在sizeof中就代表第一行整个数组,为16字节
4.4
a[0]是第一行数组名,他不在sizeof中,也没有取地址,故为第一行首元素地址,当地址进行±运算时,与指针类型有关,+1后指向第一行第二个元素,但依旧为地址,那就是4字节
5.4
a[0]+1为第一行第二个元素地址,解引用后成为int类型的元素,故为4字节
6.4
a不在sizeof中,也没有取地址,故为首元素地址,二维数组的首元素地址为第一行数组的地址,类型为int(*)[4],+1跳过一个4字节的数组,指向第二行数组,但依旧是地址,故为4字节大小
7.16

此题有两种方法:
1.a+1为第二行数组的地址,解引用后就是整个第二行数组,则sizeof后就是第二行整个数组的大小,为16字节
2.*(a+1)就是a[1],a[1]就是第二行的数组名,放在sizeof中就是求第二行整个数组的大小,为16字节

8.4
&a[0]是第一行数组的地址,+1后就是第二行数组的地址,是地址的话就是4字节
9.16
解引用第二行数组地址找到的就是第二行整个数组,sizeof后就是16字节
10.16
a不在sizeof中,也没有取地址,故为首元素地址,即为第一行数组地址,解引用就是整个第一行数组,大小为16字节
11.16
sizeof是操作符,不会执行,故也不会越界,在编译时就会算出结果

欢迎讨论与纠错,下篇也是笔试题,但是不是关于sizeof与strlen,而是会更灵活的运用

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值