指针和数组笔试题解析

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

对指针知识进行巩固


一. 一维数组

int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
//a为数组名放在sizeof函数内部就表示整个数组的大小所以为16
printf("%d\n",sizeof(a+0));
//a为数组首元素地址加0还是首元素地址所以输出为4或8
printf("%d\n",sizeof(*a));
//对数组首元素解引用得到数组首相0,所以输出4
printf("%d\n",sizeof(a+1));
//对数组首元素地址加1也就是数组第二位元素的地址所以输出4或8
printf("%d\n",sizeof(a[1]));
//a[1]=2所以输出4
printf("%d\n",sizeof(&a));
//&a取出的是数组的地址,所以输出4或8
printf("%d\n",sizeof(*&a));
//对a进行取地址和解引用相当于sizeof内只放了a,所以输出16
printf("%d\n",sizeof(&a+1));
//&a是数组的地址加1跳过整个数组,所以还是地址4或8
printf("%d\n",sizeof(&a[0]));
//第一个元素的地址,所以输出4或8
printf("%d\n",sizeof(&a[0]+1));
//第二个元素地址,所以输出4或8

输出结果
x86
在这里插入图片描述
x32
在这里插入图片描述

二.字符数组

1.字符

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
//arr单独放在sizeof里表示整个数组占有的字节数,所以输出6
printf("%d\n", sizeof(arr+0));
//arr为数组首元素地址+0还是首元素地址,所以输出4或者8
printf("%d\n", sizeof(*arr));
//对arr数组首元素地址解引用得到数组首元素a,所占字节数为1
printf("%d\n", sizeof(arr[1]));
//输出数组第二位元素b,所以输出1
printf("%d\n", sizeof(&arr));
//&arr是数组的地址,所以输出4或8
printf("%d\n", sizeof(&arr+1));
//&arr为数组地址加1跳过整个数组,还是地址所以输出4或8
printf("%d\n", sizeof(&arr[0]+1));
//&arr[0]取数组首元素地址,再加1,是数组第二位元素的地址,还是地址所以输出4或8
printf("%d\n", strlen(arr));
//strlen函数是找到/0后停止,在arr数组中没有/0所以输出值是随机值
printf("%d\n", strlen(arr+0));
//随机值
printf("%d\n", strlen(*arr));
//对数组首元素地址解引用得到首元素a,strlen函数会把a的ascii值97当作地址,会非法访问内存
printf("%d\n", strlen(arr[1]));
//arr[1]是数组二号元素得到b,strlen函数会把b的ascii值98当作地址,会非法访问内存
printf("%d\n", strlen(&arr));
//随机值
printf("%d\n", strlen(&arr+1));
//随机值但是等于上一种减6
printf("%d\n", strlen(&arr[0]+1));
//随机值但是等于上一种减1

在这里插入图片描述

在这里插入图片描述

2.字符串

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
//arr单独放在sizeof内部表示整个数组,字符串结尾隐藏/0,所以输出7
printf("%d\n", sizeof(arr+0));
//arr+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));
//表示数组首元素地址跳过整个数组的的地址,所以输出4或8
printf("%d\n", sizeof(&arr[0]+1));
//表示数组首元素地址加一得到数组二号元素地址,所以输出4或8
printf("%d\n", strlen(arr));
//arr表示数组首元素地址,strlen函数不数/0,所以输出6
printf("%d\n", strlen(arr+0));
//同上输出6
printf("%d\n", strlen(*arr));
//对数组首元素解引用得到首元素a,err
printf("%d\n", strlen(arr[1]));
//得到b,err
printf("%d\n", strlen(&arr));
//数组地址就是数组首元素地址,所以输出6
printf("%d\n", strlen(&arr+1));
//数组地址加一跳过数组,因此遍历输出随机值
printf("%d\n", strlen(&arr[0]+1));
//从数组一号元素向后遍历,输出5

在这里插入图片描述
在这里插入图片描述

char *p = "abcdef";
printf("%d\n", sizeof(p));
//p为数组首元素地址所以输出4或8
printf("%d\n", sizeof(p+1));
//p指针加一指向下一位元素的地址,所以输出4或8
printf("%d\n", sizeof(*p));
//对首元素地址解引用得到a,所以输出1
printf("%d\n", sizeof(p[0]));
//得到数组首元素a,输出1
printf("%d\n", sizeof(&p));
//数组的地址,所以输出4或8
printf("%d\n", sizeof(&p+1));
//数组的地址加一跳过整个数组,还是地址所以输出4或8
printf("%d\n", sizeof(&p[0]+1));
//数组首元素加1,输出第二位元素地址,所以输出4或8
printf("%d\n", strlen(p));
//输出6
printf("%d\n", strlen(p+1));
//输出5
printf("%d\n", strlen(*p));
//err
printf("%d\n", strlen(p[0]));
//err
printf("%d\n", strlen(&p));
//输出随机值 取地址p是相当于二级指针,第一个未知地址进行访问
printf("%d\n", strlen(&p+1));
//输出随机值且和上一个数数值没任何关系
printf("%d\n", strlen(&p[0]+1));
//输出5

三.二维数组

int a[3][4] = {0};
printf("%d\n",sizeof(a));
//a是数组名单独放在sizeof函数内,所以a代表的是整个数组,所以输出48
printf("%d\n",sizeof(a[0][0]));
//数组首元素所以输出4
printf("%d\n",sizeof(a[0]));
//a[0]代表第一行数组的数组名,放在sizeof内部表示是第一行元素的的所占字节数为16
printf("%d\n",sizeof(a[0]+1));
//a[0]+1相当于a[0][1]的地址,所以输出4或8
printf("%d\n",sizeof(*(a[0]+1)));
//相当于a[0][1]的值,所以输出4
printf("%d\n",sizeof(a+1));
//a没单独放在sizeof函数内部,也没有&,所以表示的是首元素地址,把二维数组看成一维数组,a代表的就是第一行元素的地址,a+1相当于第二行的地址,所以输出4或8
//a   &a[0]
//a+1 &a[1]
//a+2 &a[2] 
printf("%d\n",sizeof(*(a+1)));
//a是第一行数组的地址,a+1就是第二行数组的地址,所以输出16
printf("%d\n",sizeof(&a[0]+1));
//&a[0]是第一行的地址相当于a,加1为第二行的地址,所以输出4或8
printf("%d\n",sizeof(*(&a[0]+1)));
//对第二行地址进行解引用得到第二行元素,所以输出16
printf("%d\n",sizeof(*a));
//对第一行元素进行解引用得到第一行元素,所以输出16
printf("%d\n",sizeof(a[3]));
//a[3]单独放在sizeof函数内,所以a[3]代表的是整行数组, 即使越界但是sizeof函数能分析出第四行的类型
所以输出16

在这里插入图片描述

四.指针笔试题

第一题

int main()
{
  int a[5] = { 1, 2, 3, 4, 5 };
  int *ptr = (int *)(&a + 1);
  //&a是数组的地址,加1跳过整个数组
  printf( "%d,%d", *(a + 1), *(ptr - 1));
  //a是数组首元素的地址+1得到第二位元素的地址,对地址进行解引用得到第二位元素2
  //对跳整个数组的地址-1得到数组最后一位元素的地址,解引用得到5
  return 0;
}

在这里插入图片描述

第二题

//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
printf("%p\n", p + 0x1);
//p是结构体指针,所以+1跳过20个字节,所以输出0x100014
printf("%p\n", (unsigned long)p + 0x1);
//将p强制转化为长整型,+1就是0x100001
printf("%p\n", (unsigned int*)p + 0x1);
//将p转化为int指针,加一跳过四个字节
return 0;
}

在这里插入图片描述

第三题

int main()
{
  int a[4] = { 1, 2, 3, 4 };
  int *ptr1 = (int *)(&a + 1);
 // ptr1 对数组名取地址加一跳过数组
  int *ptr2 = (int *)((int)a + 1);
  //将a强制类型转换为整形,再加一,在强制类型转化为指针实际上是向右移动一个字节
  printf( "%x,%x", ptr1[-1], *ptr2);
  // ptr1[-1]等于*(ptr1-1)就打印4
  //对ptr2解引用控制四个字节00 00 00 02以16进制打印2 00 00 00
  return 0;
}

在这里插入图片描述
在这里插入图片描述

第四题

#include <stdio.h>
int main()
{
  int a[3][2] = { (0, 1), (2, 3), (4, 5) };
//  数组里放的逗号表达式,所以数组元素为 1 3 5
  int *p;
  p = a[0];
  printf( "%d", p[0]);
  // p[0]=*(p+0)=*(a[0]+0)所以输出a[0][0]等于1
return 0;
}

在这里插入图片描述

第五题

int main()
{
  int a[5][5];
  int(*p)[4];
  //p是一个数组指针一次控制四个数组参数,所以p+1一次跳过四个字节
  p = a;
  printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
  //p[4][2]=*(*(p+4)+2)
  //%d形式打印-4
  //%p形式打印
  //10000000 00000000 00000000 00000100
  //11111111 11111111 11111111 11111011
  //11111111 11111111 11111111 11111100
  // ff       ff       ff      fc   
  return 0;
}

在这里插入图片描述
在这里插入图片描述

第六题

int main()
{
  int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  int *ptr1 = (int *)(&aa + 1);
  //&a是整个数组的地址加1跳过整个数组
  int *ptr2 = (int *)(*(aa + 1));
  //二维数组数组名代表第一行数组的地址,加一跳过第一行,得到地址
  printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
  //所以输出5,10
  return 0;
}

在这里插入图片描述

第七题

#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
//数组里存放的char*指针分别指向三个元素
char**pa = a;
//pa指针指向的元素类型是char*
pa++;
//pa++移动指向下一个char*
printf("%s\n", *pa);
//对pa进行解引用得at
return 0;
}

在这里插入图片描述
在这里插入图片描述

第八题

int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);
//对cpp进行++使cpp指向c+2,对c+2进行解引用得到POINT
printf("%s\n", *--*++cpp+3);
//对cpp再++指向c+1,对c+1再-1得到c,对c解引用再移动三位,输出ER
printf("%s\n", *cpp[-2]+3);
//cpp[-2]=*(cpp-2),cpp-2指向c+3,解引用得到c+3,,再解引用移动三位输出ST
printf("%s\n", cpp[-1][-1]+1);
//cpp[-1][-1]=*((*(cpp-1)-1),cpp-1指向c+2,解引用得到c+2,c+2-1在解引用得到new,再加一输出EW
return 0;
}

在这里插入图片描述
在这里插入图片描述

总结

对于指针习题进行简单的总结,指针部分告一段落

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值