目录复制
前言
上一次我们深入理解了指针的用法,这次我们将一起理解指针的笔试题,来加深对于指针的理解,废话少说,直接开始吧~😀😀
一、指针与数组笔试题
关于这部分题目,我们得先了解一个知识:
1. sizeof(数组名),这里的数组名代表整个数组计算的是整个数组的字节大小;
2. &数组名,这里的数组名代表整个数组,取出的是整个数组的地址;
3. 除去上面两种情况后,数组名代表的就是数组首元素的地址了。
1.一维数组
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.
答案:
- 4*4 = 16;
- 由于a+0后就不再是sizeof加数组名了,这时a+0就是数组首元素的地址,所以打印的就是地址的字节大小,在32位操作系统的大小为4字节,在64位操作系统的大小为8字节;(在后面的题目中,若计算的是指针大小,本人就简写为了4/8)
- 4;
- 4/8;
- 4;
- &a是整个数组的地址,是地址,所以大小为4/8;
- *&a就相当于a,所以计算的是整个数组的大小,为16;
- 4/8;
- 4/8;
- 4/8
2.字符数组
2.1
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
printf("%d\n", strlen(arr));//8
printf("%d\n", strlen(arr+0));//9
printf("%d\n", strlen(*arr));//10
printf("%d\n", strlen(arr[1]));//11
printf("%d\n", strlen(&arr));//12
printf("%d\n", strlen(&arr+1));//13
printf("%d\n", strlen(&arr[0]+1));//14
- 1*6 = 6;
- 4/8;
- 1;
- 1;
- 4/8;
- 4/8;
- 4/8
- 因为strlen是计算传入的字符数组‘\0’之前的字符个数,而arr数组中没有‘\0’,所以计算出的是随机值;
- 随机值;
- 因为strlen要传指针,但*arr不是指针,所以会报错 ;
- 报错;
- 虽然&arr得出来的是整个数组的地址,但值和arr是一样的,只是类型不同,传入strlen后类型会被改变为char*,所以得出来的是随机值;
- 同理,得出来的依然是随机值,但和之前的随机值不同;
- 随机值,和之前的随机值不同;
2.2
char arr[] = "abcdef";
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
printf("%d\n", strlen(arr));//8
printf("%d\n", strlen(arr+0));//9
printf("%d\n", strlen(*arr));//10
printf("%d\n", strlen(arr[1]));//11
printf("%d\n", strlen(&arr));//12
printf("%d\n", strlen(&arr+1));//13
printf("%d\n", strlen(&arr[0]+1));//14
- 因为字符串的末尾会跟随’\0’,所以该数组大小为7
- 4/8
- 1
- 1
- 4/8
- 4/8
- 4/8
- 6
- 6
- 因为strlen要传指针,但*arr不是指针,所以会报错
- 报错
- 虽然&arr得出来的是整个数组的地址,但值和arr是一样的,只是类型不同,传入strlen后类型会被改变为char*,所以得出来的是6;
- 随机值
- 5
2.3
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
printf("%d\n", strlen(p));//8
printf("%d\n", strlen(p+1));//9
printf("%d\n", strlen(*p));//10
printf("%d\n", strlen(p[0]));//11
printf("%d\n", strlen(&p));//12
printf("%d\n", strlen(&p+1));//13
printf("%d\n", strlen(&p[0]+1));//14
该题是创建了一个字符指针p指向了常量字符串的首字符,不再是直接创建的数组了
- 4/8
- 4/8
- 1
- 1
- 4/8
- 4/8
- 4/8
- 6
- 5
- 报错
- 报错
- 6
- 随机值
- 5
3.二维数组
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是二维数组的数组名,a[0]是这个二维数组第一行的数组名,其余可以类比一维数组
- 3*4*4=48
- 4
- 由于a[0]是第一行的数组名,所以求出来的是第一行的大小,为4*4=16
- 4/8
- 4
- 由于a+1不是数组名,此时a是二维数组首元素的地址,4/8
- *(a+1) 相当于 a[1],所以为16
- 4/8
- &a[0]取出的是二维数组第一行的整个数组,+1后跳过整个第一行,为整个第二行,解引用后得到第二行的数组名,所以求出的是整个第二行的大小,为16
- 16
- 16
二、指针笔试题(进阶版)
1.
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
打印的结果为:2,5
int *ptr = (int *)(&a + 1) :&a取出的是整个数组,+1跳过整个整个数组,并将此地址强制类型转换为int* 赋给ptr,此时ptr-1就后退一个整形,解引用就得到了5
2.
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;
}
在32位系统上的答案是:4,2000000
a本是首元素地址,+1跳过一个int类型的数据(数值上相当与给地址+4),但现在强制类型转换为了int类型,+1就是数值上给地址+1,转换为int*类型后,ptr2指向的就是数组a的第一个数据的后三个字节的空间和第二个数据的第一个字节的空间,解引用就得到了2000000
而在64位操作系统中,指针类型的大小为8字节,而int类型只有4字节,所以无法转换
3.
#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;
}
这题有一个坑,那就是逗号表达式,所以存在与二维数组中的数只有1,3,5
答案是1
4.
#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
故答案为 “at”
5.
int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);//1
printf("%s\n", *--*++cpp+3);//2
printf("%s\n", *cpp[-2]+3);//3
printf("%s\n", cpp[-1][-1]+1);//4
return 0;
}
- ++cpp就改变了cpp的指向
答案为POINT - 前置++和前置–都改变了数组内的数据
故答案为:ER - 答案为ST
- 答案为EW