目录
- 前言
- 一、指针运算笔试题解析
- 题1
- 题2
- 题3
- 题4
- 题5
- 题6
- 题7
- 总结
前言
这期我们主要分享一下关于指针运算的笔试题
一、指针运算笔试题解析
题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
在X86环境下
假设结构体的⼤⼩是20个字节
程序输出的结构是啥?
struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}
我们来一个一个的看,第一个p+1,结构体指针+1,是不是跳过了一个结构体,也就是20字节;
0x100000+20(0x000014)=0x100014;
这里的p原本是结构体指针变量,但是这里强制转化为unsigned long类型,所以这里就不是进行指针的运算了:这里要提醒大家:大家学了指针的计算,就忘了整数的运算;
整型+1=0x100000+0x000001
最后一个:这里是将p强制转化为一个无符号整型指针类型,那+1就是跳过了一个无符号整型指针类型:
无符号整型指针+1->跳过四个字节
运行结果:
结果与我们预想的一致:
题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;
}
我们不要被这个二维数组误导了,这里面是个逗号表达式,那二维数组是这样的:
知道这个,那这题就不难了:
题4
//假设环境是x86环境,程序输出的结果是啥?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和a的类型:
- a—>类型是:int(*)[5]
- p—>类型是:int(*)[4]
我们要注意:p是一个数组指针,p指向的数组是4个整型元素的;
但是,如果将a指针赋值给p;a指针是指向二维数组的首元素地址,p也得到了这个地址,但是两个由于类型的差异,所以略有不同,这点我们可以在指针与整数的运算中体现:
p+1是跳过4个字节;而a+1是跳过5个字节的长度;
我们知道,指针减去指针的出的是两个指针间的元素个数,数组的地址是从低到高的:所以结果就是-4;但是用%d和%p打印有什么不同?
- %d是用来打印有符号整型的
- %p是用来打印地址的
-4的原码:
10000000000000000000000000000100(原)
111111111111111111111111111111111100(补)
FFFFFFFC(十六进制)
而计算存的是补码,%p的形式打印直接转化成十六进制打印出:也就是FFFFFFFC
运行结果:
题5
#include <stdio.h>
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;
}
运行结果:
题6
#include <stdio.h>
int main()
{char *a[] = {"work","at","alibaba"};char**pa = a;pa++;printf("%s\n", *pa);return 0;
}
分析:
这题其实主要理解第一行代码的指针数组:
我们知道我们定义一个字符串:
char* P = "abcdef";
表示:
这里只是将地址当做元素存入到数组中;
那这到题就不难了:
题7
#include <stdio.h>
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;
}
这题较为复杂,我们可以画图:
我们来一个一个的看:
-
**++cpp:先将cpp指针自增;即指向cp的第二个元素,解引用后指向c的最后一个元素,再进行解引用所以打印出POINT;
-
*–*++cpp+3:再将cpp自增,即指向cp的第三个元素,解引用后指向c的第二个元素,再自减,指向c的第一个元素;+3后打印出ER;
-
*cpp[-2]+3:我们先来讲cpp[-2]看成*(cpp-2);这个就不难看出了;
-
与第三个一样讲cpp[-1][-1]看成:*(*(cpp-1)-1);
运行结果:
总结
这期我们主要讲解了指针有关的题目,指针的内容到此结束了,谢谢大家关注,下期见。