今天和大家一起深度剖析一下大厂的一些指针笔试题。
我们先一起来看一下二维数组。
sizeof(a),a单独出现在sizeof内部,表示的是整个二维数组的大小,其结果为48,我们可以类比int
a[4]={1,2,3,4},这个一维数组 sizeof(a),其表示的就是一维数组的大小。
sizeof(a[0][0]),求的是第一个元素的大小,等于4
sizeof(a[0]),我们知道a[0]代表的是二维数组第一行这个一维数组首元素的地址,因为其单独放在sizeof内部,其代表的是整个这个一维数组所有元素的大小,其大小为16
sizeof(a[0]+1),a[0]+1是第一行这个一维数组第二个元素的地址,因为其没有单独放在sizeof内部,其表示指针变量的大小,其大小为4或8
sizeof(*(a[0]+1)),表示的是第一行一维数组第二个元素的大小,其结果为4.
sizeof(a+1),a+1,表示的是第二行整个数组的地址,其表示的是指针的大小,结果为4或8。
sizeof(*(a+1)),*(a+1)相当于a[1],表示的是第二行这个一维数组的首元素的地址,又因为其单独放在sizeof内部,表示的是整个一维数组的大小,其为16.
sizeof(&a[0]+1)&a[0]表示是对第一行的一维数组数组名取地址,&[0]+1表示的是第二行的地址,其结果表示的是指针变量的大小,其结果为4或8
sizeof(*(&a[0]+1)),&a[0]表示的是第一行这个整个一维数组的地址,&a[0]+1,表示的是第二行这整个一维数组的地址,对其解引用相当于拿到了第二行一维数组的首元素的地址,相当于a[1],又因为它单独放在sizeof内部,其表示的是整个第二行这个数组的大小,其大小为16.
sizeof(*a),a表示的是第一行整个二维数组的地址,*a表示的则是第一行二维数组首元素的地址,相当于a[0],a[0]单独出现在sizeof内部,所以其百事得是整个这个一维数组所有元素的大小,其大小为16.
sizeof(a[3])和sizeof(a[0]),分别代表第一行和第四行这两个一维数组首元素的地址,又因为其单独出现在sizeof内部,分别表示这两个一维数组的大小,所以其结果都为16.
我们再一起来看一下指针的一些笔试题
我们知道a+1表示的是2的地址,&a+1跳过整个数组然后再减1指向的是5的地址,所以分别对其解引用后的结果分别为5,2
这道题中假设结构体test类型变量的大小是20个字节,第一个p+1,我们知道+1跳过几个字节取决于p的类型第一个p类型为结构体类型的指针,所以跳过20个字节,p+1结果为0x100014,而对于第二个p是个无符号长整型类型对p+1,跳过一个字节,所以p+1结果为100001,对于第三个p是一个无符号整形类型的指针对p+1跳过4个字节,所以其结果为100004.
&a是整个一维数组的地址,&a+1,跳过整个数组,把他存放在整形指针ptr1 里,而第二个a因为把它转化成了整形,所以a+1只跳过 一个字节,然后把a+1的地址存放在整形指针ptr2里我们一起来看一下
这是数组里四个元素在内存里的一个存储的方式,因为ptr1是int*类型,所以ptr1-1往后跳过4个字节指向04,对其解引用也访问四个字节:04 00 00 00,所以ptr1[-1]结果为4,对于ptr2指向00,对其解引用也是访问4个字节:00 00 00 02所以*ptr2结果为2.
这个题比较容易出错的地方是(0,1 ),(2,3),(4,5)它们都是括号,所以实际上是1,3,5这三个元素
这是其元素布局,我们知道p代表的是第一行首元素的地址派p[0]等*(p+0),也就是1
这个题最好是画图来做,我们一起来看一下
我们可以清除的看到&p[4][2]和&a[4][2]所指向的位置,又因为指针-指针的绝对值等于两者之间的元素个数地址由低到高,所以&p[4][2]-&a[4][2]等于-4,打印地址打印的是补码,-4的补码是11111111111111111111111111111100,用十六进制可表示为FFFFFFFC
&aa表示的是整个数组的地址,&aa+1跳过整个数组,aa表示的是第一行整个一维数组 的地址,也就是ptr1,aa+1表示的是第二行整个一维数组的地址*(aa+1)表示的是第二行一维数组首元素的地址,也就是ptr2,一起来看图
ptr2-1表示的是5的地址,ptr1-1表示的是10的地址,对其分别解引用表示的是10和5
我们再一起来看一道比较难得题目。
我们先画一下图:
我们先看第一个printf,cpp+1是c+2的地址指向c+2,对其解引用得到c+2,c+2是第三个char*也就是P的地址对其解引用得到char* ,char*里存放的是P 的地址,对一个字符串而言只要给了首元素地址,就可以打印出来所有的元素,所以**++cpp打印最后出来的结果是POINT
再来看第二个printf,cpp+1现在指向的是c+1的地址,(第一个printf++cpp的时候就已经指向c+2的位置了),*++cpp得到c+1,--c+1得到了c,对c解引用得到了第一个char*,第一个char*代表E的地址,再加3,就得到了T的地址,所以*c-- *++cpp+3最后打印出来的结果是ER
我们再来看第三个printf,首先呢cpp[-2]=*(cpp-2),cpp-2是c+3的地址,*(cpp-2)得到的是c+3,*cpp[-2]也就是*(c+3),得到的是最后一个char*最后一个char*代表的是F的地址,*cpp[-2]再加3,得到的是S的地址,所以*cpp[-2]+3,最后打印出来的结果是ST
我们再来看一下最后一个printf,cpp[-1][-1]等价于*(*(cpp-1)-1),(第三个printf的时候cpp-2并没有改变cpp原来的值因为它并没有赋值给cpp,而前两个printf是++cpp自增1,相当于+1后再赋值给了cpp,cpp还是指向c+1的位置)*(cpp-1)得到的是c+2,c+2再减1等于c+1,对(c+1)解引用得到的是第二个char*也就是N的地址,然后最后再+1,得到的是E的地址,所以cpp[-1][-1]+1最后打印出来的结果是EW。
今天一些大厂指针的一些笔试题就和大家分享到这了,希望大家都能有所收获。