前言:
祝贺你披荆斩棘来到笔试题的最后一篇,相比前两笔试题不同的是,这篇笔试题更考验你的基础知识
是否扎实,是否真正地理解指针是什么,所以你准备好了吗?OK让我们喊一下干饭人的口号!
知识点回顾
- 数组名就是首元素的地址
- 当数组名为下面两种情况时有特殊含义:(1) sizeof(数组名),这里的数组名代表的是整个数组,计算的是整个数组的大小。(2) &数组 名,这里表示整个数组的地址,类型为一个数组指针类型,注意除了以上两种情况的是他表达形式,数组名都表示数组首元素的地址。
- 二维数组名:二维数组名代表首行元素的地址
- sizeof只关注占用空间的大小,单位是字节sizeof不关注类型,sizeof是操作符
- strlen关注的字符串中\0的为止,计算的是\0之前出现了多少个字符,strlen只针对字符串,strlen是库函数,函数传参为指针。(3)要注意区分数组名单独放在关键字sizeof中和单独放在函数strlen中的区别,大概的内容就是,单独放在sizeof中时指的是计算整个数组的大小,而单独放在函数strlen中时则指的是数组首元素地址。
笔试题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;
}
✔解答环节:这里要用到学习数组时的一个知识点那就是a[i]=*(a+i),所以第一个结果为a[1]=2
&a+1跳过了整个数组指向如位置,然后再强制类型转换为整形指针存放于整形指针ptr,所以
ptr-1指向数组下标为4的元素即a[4]=5,所以是出结果为(2 , 5)
笔试题2
题目:下列代码假设p 的值为0x100000。 如下表表达式的值分别为多少?
已知,结构体Test类型的变量大小是20个字节
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
解答环节:因为p是结构体指针,0x1是一个16进制的数字为1,p+1即跳过一个结构体
所以第一个表达式p+1=0x100020,第二个表达式中,p被强制转换成了一个整型数字
再加上0x1,所以第二个表示为0x100001,第三个表达式与第一个相似,只不过是将
结构体类型指针转化为整形指针,此时p访问权限为4个字节,所以第三个表达式为
0x100004(0x100014 0x100001 0x100004).
笔试题3
问题:下列代码输出结果为?
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;
}
解答环节:第一个表达式中(&a+1)在如图位置即跳过整个数组,在强制值类型转化成整形指针,又ptr1[-1]=*(ptr-1)
所以等于a[3]=4,第二个表达式相对要困难一点,首先要理解(int)a+1是什么意思,其实是将数组首元素地址转换成
整形再加1,那就相当于地址值加1,地址值加1又等于跳过一个字节,然后再转换为整形指针存放于ptr2中,如图
对ptr2解引用时从指向如图向后访问四个字节(假设机器为小端字节序存放),即(2 00 00 00)
👀小结:是不是掉坑了呢,这道题主要容易忽略指针运算和整数运算的区别,以及大小端字节序在内存中的存放与读取
即小端:低字节放在低地址处,读取时从高地址向低地址读取,大端反之。
笔试题4
问题:下列代码的输出结果是?
#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,0,0,0},a[0]代表第一行数组首元素地址存放于p中,p[0]相当于解引用所以结果为1
笔试题5
问题:下列代码的输出结果是?
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;
}
解答环节:因为p是一个数组指针指向的数组有4个元素,具体解答见图
👀***小结:这道题主要是要理解int(p)[4],它是一个数组指针指向的数组有4个元素。**
笔试题6
问题:下列代码的输出结果是?
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;
}
解答:如图
笔试题7
问题:下列代码的输出结果是?
#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
🔎解答:要注意的是数组a是一个指针数组,所以数组名是数组首元素地址也就是’w’的地址,所以
要存放在字符二级指针pa中,详如图(注意图中pa指向的是w的地址,不是直接指向字符w的)
好家伙累死我了,还有最后一道压轴题,坚持住!
笔试题8(压轴)
🔎好吧(●’◡’●),细细品味,浅浅微笑
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;
}
解答:分四幅图便于理解
芜湖~~毁灭吧!