深度讲解 —— 指针和数组笔试题(C语言进阶)

1. sizeof 和 strlen 的区别

在我们刷笔试题之前,我们首先要知道 sizeof 和 strlen 的区别,因为下面我们讲的笔试题和 sizeof , strlen 息息相关

sizeof是计算类型和变量的大小:

char ch[10] = "abcdef";
sizeof(ch);  —— 这个计算的大小为10字节

strlen是计算字符串长度:
———— 当 strlen 读到字符 ’ \0 ’ 的时候不在往后面读

char ch[10] = "abcdef";
strlen(ch);  —— 这个计算的大小为6

数组名的意义

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
  2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
  3. 除此之外所有的数组名都表示首元素的地址

2. 一维整型数组 —— sizeof

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

在这里插入图片描述
详细解析:


1. —— 16  a为首元素地址,单独放在了sizeof中,表示整个数组 —— 整个数组的大小为(4*4 = 16)字节
2. —— 4  a为首元素地址,(a+0)也是首元素地址,首元素地址没有单独放在sizeof中,表示首元素地址 —— 首
         元素地址的大小为48字节
3. —— 4  a为首元素的地址,*a表示为首元素,首元素为int类型 —— 占4个字节
4. —— 4  a为首元素地址,(a+1)是第二个元素的地址 —— 第二个元素地址为48字节
5. —— 4  a[1]表示第二个元素 —— 占4字节
6. —— 4  &a表示整个数组的地址,整个数组的地址也是地址 —— 只要是地址就是48字节
7. —— 16 &a表示整个数组的地址,对整个数组解引用找到整个数组 —— 数组的大小为16字节
8. —— 4  &a表示整个数组的地址,(&a+1)表示数组 + 1 —— 只要是地址就是48字节
9. —— 4  a[0]表示首元素,&a[0]表示首元素地址 —— 地址为48字节
10.—— 4  &a[0]表示首元素地址,&a[0] + 1表示第二个元素地址 —— 地址为48字节

3、字符串

第一组

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

在这里插入图片描述

详细解析:

1 —— 6  arr单独放在sizeof中,表示整个数组,整个数组的大小为6个字节
2 —— 4/8  arr没有单独放在sizeof中,表示首元素的地址,首元素的地址大小为48个字节
3 —— 1  arr为首元素地址,对arr解引用,表示首元素,首元素是字符类型,占1个字节
4 —— 1  arr[1] 表示首元素,首元素是字符类型,占1个字节
5 —— 4/8  arr为首元素地址,&arr表示整个数组的地址,地址占48个字节
6 —— 4/8  &arr+1表示整个数组+1,虽然是野指针了,但是还是地址,占48字节
7 —— 4/8  arr[0]表示首元素,&arr[0]首元素地址,&arr[0]+1表示第二个元素的地址,占48字节

第二组

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

在这里插入图片描述

详细解析:

1 —— 随机数  strlen是接收地址,然后找\0,arr为首元素地址,但是元素中没有\0,所以为随机值
2 —— 随机值  arr+0为首元素地址,数组中没有\0,所以为随机值
3 —— err  *arr为a —— a的ASCII码值为97,所以以97位地址(野指针)向后找\0 —— 报错
4 —— err  arr[1]为第二个元素b —— b的ASCII码值为98, —— 报错
5 —— 随机值  &arr是整个数组的地址,整个数组的地址和数组首元素的地址是相同的,arr数组中没有\0,所以为随机值
6 —— 随机值  &arr+1是整个数组+1,在数组外面没有办法确定\0什么时候出现,所以为随机值
7 —— 随机值  arr[0]首元素,&arr[0]首元素地址,&arr[0]+1第二个元素地址,不能确定\0什么时候出现,所以为随机值

第三组

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

在这里插入图片描述

详细解析:

1 —— 7  arr单独放在了sizeof中,arr表示整个数组,字符窜的末尾隐藏这\0,大小为7
2 —— 4/8  arr没有单独放在sizeof中,arr+0表示首元素地址,地址为48字节
3 —— 1  arr为首元素地址,*arr表示首元素,元素为char类型,大小为1字节
4 —— 1  arr[1]第二个元素, 大小为1字节
5 —— 4/8  &arr为整个数组的地址,地址大小为48字节
6 —— 4/8  &arr+1表示整个数组+1的地址,地址大小为48个字节
7 —— 4/8  arr[0]首元素,&arr[0]首元素地址,&arr[0]+1第二个元素地址,地址大小为48字节

第四组

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

在这里插入图片描述

详细解析:

1 —— 6  arr为首元素地址,从首元素向后找\0,第七个元素为\0,所以计算字符个数为6
2 —— 6  arr+0为首元素地址,所以计算字符的个数为6
3 —— err  *arr为首元素a,a的ASCII码值97,访问地址97为非法访问 —— 错误
4 —— err  arr[1]为第二个元素b,b的ASCII码值为98,访问地址98为非法访问 —— 错误
5 —— 6  &arr表示整个数的地址,整个数组的地址和首元素的地址相同,所以计算字符个数为6
6 —— 随机值  &arr+1表示整个数组加+1,为野指针,不在数组中,所以不能确定\0的位置。
7 —— 5   arr[0]首元素,&arr[0]首元素地址,&arr[0]+1第二个元素地址,所以计算字符个数为5

第五组

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

在这里插入图片描述

详细解析:

1 —— 4/8  p为指针,为第一个元素a的地址,指针占48个字节
2 —— 4/8  P+1为第二个元素的地址,指针占48个字节
3 —— 1  *p为第一个元素a,a占一个字节
4 —— 1  p[0]为第一个元素,占1个字节
5 —— 4/8  &p是对指针p取地址,只要是地址就是占48个字节
6 —— 4/8  &p+1是丢指针p的地址+1,地址占48字节
7 —— 4/8  p[0]是第一个元素a,&p[0]是对a取地址,&p[0]+1为b的地址,地址占48字节

第六组

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

在这里插入图片描述

详细解析:

1 —— 6  p为字符串的首元素地址,所以字符串的大小为6
2 —— 5  p+1为第二个元素b的地址,所以计算字符个数为5
3 —— err  *p为第一元素a,a的ASCII的值为97,访问地址97为非法访问 —— err
4 —— err  p[0]为第一个元素,—— err
5 —— 随机值  &p为指针p的地址,从指针p的地址然后开始向后找\0,\0的位置并不确定,所以为随机值
6 —— 随机值  &p+1为指针p的地址+1,从指针p+1的地址然后找\0,\0的位置无法确定,所以为随机值
7 —— 5  p[0]为元素a,&p[0]为元素a的地址,&p[0]+1为b的地址,所以计算的字符串大小为5

4、二维数组

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

在这里插入图片描述

详细解析:

1.当我们计算二维数组的时候要把其中sizeof中的关系是化到最简,
如*(arr+1= arr[1]
2.可以把arr的二维数看做是有几个一维数组组成的,arr[0]为第0行数组的地址,arr[1]为第一行的数组,依次类推。


1 —— 48  a为首元素地址,单独的放在了sizeof的内部,表示整个数组的大小为48
2 —— 4  arr[0][0]为首元素,大小为4
3 —— 16  arr[0]为二维数组第一行数组首的地址,单独放在了sizeof的内部,表示第一行的数组,大小为16
4 —— 4  arr[0]为第一行数组首元素地址,没有单独放在sizeof中,所以arr[0]+1表示第二个元素的地址,大小为48
5 —— 4  *(arr[0]+1)可以化简为arr[0][1],表示第一行第二个元素,大小为4
6 —— 4  a为首元素地址,没有单独放在sizeof中,a+1表示第一行第二个元素,大小为4
7 —— 16  *(arr+1)可以化简为arr[1],arr[1]为第二行首元素地址,单独放在sizeof中,表示第二行的地址,大小为16
8 —— 4  arr[0]表示为第一行的首元素地址,&arr[0]对首元素的地址取地址,&arr[0]+1对首元素的地址的地址+1,地址的大小为48
9 —— 16  &arr[0]+1对首元素的地址的地址+1,表示第二行首元素地址的地址,解引用,表示第二行首元素的地址,单独放在sizeof中,大小为16
10 —— 16  *a 等价与 *(a+0) 等价与a[0],arr[0],单独放在sizeof中,表示第一行的地址,大小为16
11 —— 16  arr[3]单独放在sizeof中,表示第四行数组的地址,虽然越界了,但大小还是为16
  • 17
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT技术博主-方兴未艾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值