🎇作者:小树苗渴望变成参天大树
🧨作者宣言:认真写好每一篇博客
🎊作者gitee:link
🎉指针笔试题详解
- 💥前言
- 💦一、指针和数组面试题解析
- 💨1.1一维数组
- 💢1.2字符数组
- 💤1.3二维数组
- 🎄二、指针面试题
- 💖三、总结
💥前言
各位友友们,我们又见面了,答应大家要更新的指针练习题他终于来了,让大家久等了,好,我们开始进入正题。
💦一、指针和数组面试题解析
我们先来补充一个知识点:数组名的意义:
- sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
- &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
- 除此之外所有的数组名都表示首元素的地址。
💨1.1一维数组
//一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));//数组名单独在sizeof内部表示整个数组,所以计算的是在整个数组的大小,//4*4=16
printf("%d\n",sizeof(a+0));//数组名不是单独在sizeof内部,所以数组名代表首元素地址,a+0还是首元素地址,是地址就是4/8个字节//4/8
printf("%d\n",sizeof(*a));//数组名不是单独在sizeof内部,便是首元素地址,解引用是首元素,sizeof计算的是首元素的大仙,是整型,所以就为4个字节//4
printf("%d\n",sizeof(a+1));//数组名不是单独在sizeof内部,所以数组名代表首元素地址,a+1就是第二个元素的地址,是地址就是4/8个字节//4/8
printf("%d\n",sizeof(a[1]));//a[1]表示数组的第二个元素,计算的是一个整型数的大小,所以是4个字节//4
printf("%d\n",sizeof(&a));//&a取出的整个数组的地址,也是地址,大小为4/8个字节//4/8
printf("%d\n",sizeof(*&a));//&a取出的是整个数组的地址,在进行解引用得到整个数组,大小为16个字节,取地址在解引用等于*&a=a,相当于在sizeof内部单独放了个数组名//16
printf("%d\n",sizeof(&a+1));//&a取出的是整个数组的地址,加1跳过整个数组的地址,是地址就是4/8个字节//4/8
printf("%d\n",sizeof(&a[0]));//&a[0]取出的是数组第一个元素的地址,是地址,大小为4/8个字节//4/8
printf("%d\n",sizeof(&a[0]+1));//&arr[0]取出的是数组第一个元素的地址在加1就是指向数组第二个元素的地址,是地址,大小为4/8个字节。//4/8
特别说明sizeof不存在非法访问的情况,1他不会使用你越界的那块地址,他的运行在编译截断就会完成,我们目前知道就行了,不需要过多去研究。
运行结果:
💢1.2字符数组
//字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//数组名单独在sizeof内部,表示整个数组,所以大小为6个字节。//6
printf("%d\n", sizeof(arr+0));//arr不是单独在sizeof内部,所以表示首元素的地址加0还是表示首元素的地址,是地址就是4/8个字节//4/8
printf("%d\n", sizeof(*arr));//arr不是单独在sizeof内部,所以表示首元素的地址,在解引用表示首元素,因为是char类型,所以大小为1个字节//1
printf("%d\n", sizeof(arr[1]));//arr[1]表示数组的第二个元素,大小为1个字节//1
printf("%d\n", sizeof(&arr));//&arr表示整个数组的地址,是地址就是4/8个字节//4/8
printf("%d\n", sizeof(&arr+1));//&arr取出的是整个数组的地址,加1跳过整个数组的地址,是地址就是4/8个字节//4/8
printf("%d\n", sizeof(&arr[0]+1));//&arr[0]取出的是数组第一个元素的地址在加1就是指向数组第二个元素的地址,是地址,大小为4/8个字节。//4/8size_t strlen(const char* str)printf("%d\n", strlen(arr));//因为arr表示首元素地址,strlen只有看到\0才会停止下来,所以这个答案是随机值//随机值
printf("%d\n", strlen(arr+0));//arr+0也是表示第一个元素的地址,答案也是随机值//随机值
//printf("%d\n", strlen(*arr));//arr表示数组第一个元素的地址,在解引用表示数组第一个元素,但是strlen只能接收地址,所以会报错//error
//printf("%d\n", strlen(arr[1]));//同上一个//error
printf("%d\n", strlen(&arr));//&arr虽然是数组的地址,但是也是从数组起始位置开始的,计算的还是随机值//随机值
printf("%d\n", strlen(&arr+1));//&arr是数组的地址,&arr+1是跳过整个数组的地址,求字符串长度也是随机值//随机值
printf("%d\n", strlen(&arr[0]+1));//&arr[0] + 1是第二个元素的地址,是'b'的地址,求字符串长度也是随机值//随机值
运行结果:
char arr[] = "abcdef";//这是一个字符数组,后面默认会有一个\0,在计算数组大小的时候\0算字符串内容,但在计算长度的时候不算在字符串长度内。printf("%d\n", sizeof(arr));//数组名单独在sizeof内部,计算的是整个数组的大小,所以大小为7个字节//7
printf("%d\n", sizeof(arr+0));//arr不是单独放在sizeof内部,所以arr表示数组名首元素的地址,arr+0也表示数组首元素的地址,是地址大小就是4/8个字节//4/8
printf("%d\n", sizeof(*arr));//arr不是单独放在sizeof内部,所以arr表示数组名首元素的地址,在进行解引用的是得到的首元素,sizeof计算的是一个字符类型的元素大小,所以大小为1个字节//1
printf("%d\n", sizeof(arr[1]));//arr[1]表示数组第二个元素,计算一个字符类型元素的大小,也为1个字节//1
printf("%d\n", sizeof(&arr));//&arr取出的是整个数组的地址,是地址就是4/8个字节//4/8
printf("%d\n", sizeof(&arr+1));//&arr取出的是整个数组的地址,加1跳过整个数组的地址,是地址就是4/8个字节//4/8
printf("%d\n", sizeof(&arr[0]+1));//&arr[0]取出的是数组第一个元素的的地址,加1指向数组的第二个元素的地址,是地址就是4/8个字节//4/8printf("%d\n", strlen(arr));//arr是数组首元素的地址,从首元素开始计算字符串的长度,到\0停止,所以长度为6//6
printf("%d\n", strlen(arr+0));//arr是数组首元素的地址,arr+0也是数组首元素的地址,所以长度为6//6
printf("%d\n", strlen(*arr));//arr是数组首元素的地址,*解引用得到了首元素a,需要传地址过去,所以会报错//error
printf("%d\n", strlen(arr[1]));//同上一个//error
printf("%d\n", strlen(&arr));//&arr取到的整个数组地址的大小,和首元素的地址大小是相同的,所以计算的长度是6//6
printf("%d\n", strlen(&arr+1));//&arr取到的整个数组地址的大小,加1跳过整个数组,因为后面的空间不知道是啥样的,不知道啥时候找到\0,因为不会访问后面的空间,所以不会出现非法访问,所以这题的长度为随机值//随机值
printf("%d\n", strlen(&arr[0]+1));//&arr[0]取到的是数组首元素的地址,加1跳过一个元素,指向第二个元素的地址,所以从第二个元素开始计算字符串长度,所以长度为5//5
运行结果:
char *p = "abcdef";//这是一个字符指针用来存取字符串的地址的,p里面保存的是字符串首元素的地址,原因是,有首元素的地址就能找整个字符串,因为有\0作为结束标志。printf("%d\n", sizeof(p));//p是指针,保存的是地址,是地址大小就为4/8个字节//4/8
printf("%d\n", sizeof(p+1));//p是首元素的地址,p+1指向第二个元素的地址,是地址,大小为4/8个字节
printf("%d\n", sizeof(*p));//p是首元素的地址,*解引用得到首元素a,a是一个字符类型,计算大小为1个字节//1
printf("%d\n", sizeof(p[0]));//同上一个//1
printf("%d\n", sizeof(&p));//&p是取出来的指针变量的地址,是地址,大小就是4/8个字节//4/8
printf("%d\n", sizeof(&p+1));//&p + 1是跳过p变量后的地址,4/8字节
printf("%d\n", sizeof(&p[0]+1));//p[0]就是‘a’,&p[0]就是a的地址,+1,就是b的地址,是地址就是4/8printf("%d\n", strlen(p));//p是首元素的地址,从这个位置开始计算字符串长度,因为有\0作为结束标志,所以长度为6//6
printf("%d\n", strlen(p+1));//p是首元素的地址,+1指向的是b的地址,从b开始计算长度,为5//5
printf("%d\n", strlen(*p));//*p为元素,应该传地址,所以会报错//error
printf("%d\n", strlen(p[0]));//同上一个//error
printf("%d\n", strlen(&p))//&p拿到的是p这个指针变量的起始地址,找不到\0,所以从这里开始求字符串长度是随机值//随机值
printf("%d\n", strlen(&p+1));//&p+1是跳过p变量的地址,从这里开始求字符串长度也是随机值//随机值
printf("%d\n", strlen(&p[0]+1));//&p[0] + 1是b的地址,从b的地址向后数字符串的长度是5//5
运行结果:
💤1.3二维数组
//二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));//数组名单独在sizeof内部,计算的是整个数组的大小,为4*3*4=48//48
printf("%d\n",sizeof(a[0][0]));//a[0][0]是数组第一行第一个元素,所以大小为4个字节//4
printf("%d\n",sizeof(a[0]));//a[0]表示的是数组第一行的地址,是单独放在sizeof内部,计算的是第一行全部元素的大小,为4*4=16个字节//16
printf("%d\n",sizeof(a[0]+1));//a[0]作为第一行的数组名,没有单独放在sizeof内部,没有取地址,表示的就是数组首元素的地址,那就是a[0][0]的地址,a[0]+1就是第一行第二个元素的地址,是地址就是4/8个字节//4/8
printf("%d\n",sizeof(*(a[0]+1)));//*(a[0] + 1)是第一行第2个元素,计算的是元素的大小-4个字节//4
printf("%d\n",sizeof(a+1));//a是二维数组的数组名,数组名表示首元素的地址,就是第一行的地址,a+1就是第二行的地址,第二行的地址也是地址,是地址就是4/8 //4/8
printf("%d\n",sizeof(*(a+1)));//a+1是第二行的地址,*(a+1)表示的就是第二行,*(a+1)--a[1] //16
printf("%d\n",sizeof(&a[0]+1));//&a[0]是第一行的地址,&a[0]+1是第二行的地址,地址的大小就是4/8//4/8
printf("%d\n",sizeof(*(&a[0]+1)));//*(&a[0] + 1) 是对第二行的地址解引用,得到的就是第二行,计算的就是第二行的大小//16
printf("%d\n",sizeof(*a));//a表示首元素的地址,就是第一行的地址,*a就是第一行,计算的就是第一行的大小//16
printf("%d\n",sizeof(a[3]));//如果数组存在第四行,a[3]就是第四行的数组名,数组名单独放在sizeof内部,计算的是第四行的大小//16
运行结果:
🎄二、指针面试题
第一题:
int main()
{int a[5] = { 1, 2, 3, 4, 5 };int *ptr = (int *)(&a + 1);printf( "%d,%d", *(a + 1), *(ptr - 1));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);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}
详细图解:
运行结果:
第三题:
int main()
{int a[4] = { 1, 2, 3, 4 };int *ptr1 = (int *)(&a + 1);int *ptr2 = (int *)((int)a + 1);printf( "%x,%x", ptr1[-1], *ptr2);return 0;
}
详细图解:
运行结果:
第四题:
#include <stdio.h>
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };int *p;p = a[0];printf( "%d", p[0]);return 0;
}
详细图解:
运行结果:
第五题:
int main()
{int a[5][5];int(*p)[4];p = a;printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);return 0;
}
详细图解:
运行结果:
第六题:
int main()
{int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int *ptr1 = (int *)(&aa + 1);int *ptr2 = (int *)(*(aa + 1));printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}
详细图解:
运行结果:
第七题:
#include <stdio.h>
int main()
{char *a[] = {"work","at","alibaba"};char**pa = a;pa++;printf("%s\n", *pa);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);printf("%s\n", *--*++cpp+3);printf("%s\n", *cpp[-2]+3);printf("%s\n", cpp[-1][-1]+1);return 0;
}
详细图解:
运行结果:
💖三、总结
博主花了很长实间用图的放是来和大家讲解指针方面的练习题,希望读者能认真将这些题目弄懂,学会,才是关键,今天的内容很充实,大家可以细心去品味一下这些题目,查缺补漏。那我们今天的讲解就到此结束了,我们下篇再见