八大指针笔试题带你overcome指针

作者主页:paper jie的博客_CSDN博客-C语言,算法详解领域博主

本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。

本文录入于《C语言》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将C语言基础知识一网打尽,希望可以帮到读者们哦。

其他专栏:《系统解析C语言》《算法详解》《C语言-语法篇》

内容分享:本期将用八大笔试题带你战胜指针,各位看官姥爷快搬好小板凳坐好叭。

    -------- 不要998,不要98,只要一键三连,三连买不了吃亏,买不了上当

前言

上期关于指针的文章,我们用多个试题对指针与数组的关系进行了全面多方位的讲解。这期文章我们将用八道经典的指针笔试题来全面多方位来了解指针。

第一题

答案是多少呢?为什么是这个答案呢?

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是数组首元素的地址,而&a是取出的整个地址。所以a+1就是第二个元素的地址,解引用就是2。&a+1就是跳过整个数组,在5元素的后面,强制类型为int就意味着它后面地址加减的单位都是int类型。ptr就是&a+1的地址,所以ptr-1就是向前减一个int类型,就指向了5的地址,解引用就是5。

八大指针笔试题带你overcome指针_第1张图片

 

第二题

假设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;
}

分析

通过提示,我们知道他是一个结构体指针类型,大小为20个字节,地址为0x100000。0x1就是p+1就是加一个20大小的结构体类型,就是0x100000+20=0x100014。unsigned long p 就是将p转化为整型,整型加1就是加1.结果就是0x100000+1=0x100001 unsigned int* p就是将p转化为指针类型,所以p+1就是加了一个指针大小0x100000+4=0x100004

八大指针笔试题带你overcome指针_第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;
}

分析

a是首元素的地址,&a+1取出的是整个数组的地址 int*(&a+1)就是将&a+1的类型转化为int*的类型,ptr[-1]可以理解为*(ptr-1),ptr就是&a+1,所以ptr-1就是减一个int*类型大小,所以就在元素4的地址,解引用就是4 int a就是将地址a转化为整型,整型加1就是加1 ,我们又知道,在内存中一个地址就是一个字节,这里加1,所以a+1指向的内容就是00到02 0x02000000

八大指针笔试题带你overcome指针_第3张图片

第四题

答案是什么呢?为什么呢?

#include 
int main()
{
 int a[3][2] = { (0, 1), (2, 3), (4, 5) };
 int *p;
 p = a[0];
 printf( "%d", p[0]);
 return 0;
}

解析

通过观察:我们可以发现,a数组里面是(),所以是逗号表达式,保留右边的值,所以()里的值是1,2,3未满就补0,后面都是0,所以数组中布局就是画图后的样子。

p是a[0]的地址,而a[0]是代表的第一行,我们可以把a[0]理解为第一行的数组名,所以a[0]是首元素的地址,解引用就是1

八大指针笔试题带你overcome指针_第4张图片

第五题

答案是多少呢?为什么是这样呢?

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;
}

  解析

a数组是一个五行五列的二维数组 a是起始元素的地址 将a的地址赋给p 且q是一个数组指针 p的类型是int[4]。
所以p每加一跳过4个元素 所以p[4]就相当于*(p+4) p的地址就是画图后的地址  两地址相减结果就是中间元素的个数 所以&p[4][2]-&a[4][2]=-4
我们知道电脑中存的都是补码
原码10000000000000000000000000000100
反码11111111111111111111111111111011
补码11111111111111111111111111111100
以%P打印就直接把补码当做地址打印了
以%d打印还是-4

 

八大指针笔试题带你overcome指针_第5张图片

第六题

答案是多少呢?为什么是这样呢?

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;
}

解析

aa是首元素的地址,就是第一行的地址 &aa取出的是整个二维数组的地址
ptr1=&aa+1 &aa+1被转化为int*类型 所以ptr-1,就是减去一个int*类型大小,这时ptr指向10元素的地址,解引用为10

aa+1就是第一行的地址加1到第二行的地址,我们发现aa+1的类型也是int*,前面的int*就没用了。就可以理解为:int*ptr=*(aa+1),我们又可以把*(aa+1)理解为aa[1],aa[1]为第二行数组名,就是首元素地址,又因为ptr==*(aa+1)==aa[1],所以ptr-1就是指向元素5,解引用就是5

八大指针笔试题带你overcome指针_第6张图片

 

第七题

答案是多少呢?为什么是这样呢?

#include 
int main()
{
 char *a[] = {"work","at","alibaba"};
 char**pa = a;
 pa++;
 printf("%s\n", *pa);
 return 0;
}

解析

我们要知道数组a里面存的char*类型的元素,是work,at,alibaba首元素的地址

用二级指针存放a的地址,pa==a,pa++==a++,a是首元素的地址,pa++==a++就是第二个元素的地址。

*pa就是at首字母的地址,%s就是通过首字符地址打印这一串字符

八大指针笔试题带你overcome指针_第7张图片

 

第八题

答案是多少呢?为什么是这样呢?

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;
}

解析

c数组存放的是字符串首元素的地址,cp数组存放的是这些首元素的地址的地址,cpp存放的是cp的地址。这里我们还要注意一个点:++和--是直接改变了它们的值,会影响后面的计算的。

八大指针笔试题带你overcome指针_第8张图片

 


你可能感兴趣的:(C语言,c语言,开发语言)