🔥🔥🔥经典题:
🌵笔试题1:
🔺特别注意:
①int* ptr = (int*)(&a + 1);
//&a取出的是整个数组的地址,因此&a的类型是int(*)[5],该类型+-1跳过的是5个int型
//强制类型转换,类型发生变化,而值不变
②printf("%d,%d", *(a + 1), *(ptr - 1));
//*(ptr-1)为什么只跳过1个int型,因为ptr的类型是int*,该类型+-1跳过1个int型
若int* p=&a;*说明p是指针变量,int说明p指向的对象是int类型。p的类型是int*
🔸本题答案:2,5
🔸代码如下:
#include <stdio.h> 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:
🔺特别注意:
这里的0x1是十六进制,转换成十进制为1
已知p的值是0x100000,
①printf("%p\n", p + 0x1);
//p是一个结构体类型指针变量,p+-1代表着跳过一个结构体类型大小
若p是一个整型指针变量,p+-1代表着跳过一个整型大小
②printf("%p\n", (unsigned long)p + 0x1);
(unsigned long)p,p的类型发生变化但值不变,
p的值是0x100000,转换成unsigned int类型后为1048576,+1为1048577,该值的地址就是0x100001
③printf("%p\n", (unsigned int*)p + 0x1);
//若p是一个整型指针,p+-1代表着跳过一个无符号整型大小
🔸本题答案:
0x100014,0x100001,0x100004
🔸代码如下:
#include <stdio.h> 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; }
🌵笔试题3:
🔺特别注意:
①int* ptr2 = (int*)((int)a + 1);
//a是数组首元素的地址,强制类型转换成int型,值不变,类型发生变化
//若a=0x0012ff40,则a+1=0x0012ff44,(int)a+1=0x0012ff41
该数组在内存中的存储,vs采用小端存储模式,0x00 00 00 01在内存中存储为01 00 00 00
②printf("%x,%x", ptr1[-1], *ptr2);
//ptr2的类型是int*,解引用操作访问1个整型大小,再按十六进制打印
🔸本题答案:4,2000000
🔸代码如下:
#include <stdio.h> 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; }
🌵笔试题4:
🔺 特别注意:
①int a[3][2] = { (0,1),(2,3),(4,5) };
//这里是逗号表达式,注意是(),不是 { } ,看下图体会区别!
🔸本题答案:1
🔸代码如下:
#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; }
🌵笔试题5:
🔺 特别注意:
①int a[5][5];
//在二维数组int a[5][5]中,a为数组首元素的地址,类型为int (*)[5];
②int(*p)[4];
//p指向的数组有4个元素,每个为int型,+1跳过1个(4个int类型的数组)
③p = a;
int (*)[4]=int (*)[5];
printf("%p\n", &p[4][2] - &a[4][2]);
//&p[4][2]和&*(*(p+4)+2)一样。p是个数组指针,+4跳过4个(4个int类型的数组)
//p++为上图绿色图标,橙色为p[4]解引用
④&p[4][2] - &a[4][2]=-4;
//-4按%p打印,是将-4的补码转换成十六进制
原码:
10000000 00000000 00000000 00000100
反码:
11111111 11111111 11111111 11111011
补码:
11111111 11111111 11111111 11111100
得到 0xFF FF FF FC
🔸本题答案:FF FF FF FC,-4
🔸代码如下:
#include <stdio.h> 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; }
🌵笔试题6:
🔺特别注意:
①int* ptr1 = (int*)(&aa + 1);
//&aa得到的是整个数组的地址,+1跳过整个二维数组
②int* ptr2 = (int*)(*(aa + 1));
//aa为二维数组第一行的地址,
*(aa + 1)=aa[1],aa[1]为第二行首元素的地址,此类型为int*,因此这里的(int*)多余
🔸本题答案:10,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; }
🌵笔试题7:
🔺 特别注意:
①char* a[ ] = { "work","at","alibaba" };
//该数组存的是work、at、alibaba首元素的地址
②char** pa = a;
//pa指向的是a数组第二个元素,解引用后得到at首元素的地址
③printf("%s\n", *pa);
//printf打印时,%s会根据首元素的地址,向后打印,遇到\0停止
🔸本题答案:at
🔸代码如下:
#include <stdio.h> int main() { char* a[] = { "work","at","alibaba" }; char** pa = a; pa++; printf("%s\n", *pa); return 0; }
🔥🔥🔥笔试题8:
本题为指针笔试题的集大成者
🔺特别注意:
代码剖析:
++cpp后cpp指向的地址会发生变化
①printf("%s\n", **++cpp);
//++cpp后,cpp指向c+2,第一次解引用后得到c+2,而c+2指向数组c第三个元素,第二次解引用后得到数组c第三个元素“POINT”首字符的地址,printf打印时,%s根据首字符P的地址向后打印,遇到\0停止
②printf("%s\n", *--*++cpp+3);
//++cpp后,cpp指向c+1,第一次解引用后得到c+1,c+1再-1指向数组c第一个元素,第二次解引用后得到数组c第一个元素"ENTER"首字符的地址,+3得到T的地址,printf打印时,%s根据字符T的地址向后打印,遇到\0停止
③printf("%s\n", *cpp[-2]+3);
//**(cpp-2)+3;cpp-2指向c+3,第一次解引用后得到c+3,该地址指向数组c第四个元素,第二次解引用后得到数组c第四个元素"FIRST"首字符的地址,+3得到R的地址,printf打印时,%s根据字符R的地址向后打印,遇到\0停止
④printf("%s\n", cpp[-1][-1]+1);
//cpp[-1][-1]+1和*(*(cpp-1)-1)+1;cpp-1指向c+2,第一次解引用后得到c+2,该地址-1指向数组c第二个元素,第二次解引用后得到数组c第二个元素"NEW"首字符的地址,+1得到E的地址,printf打印时,%s根据字符E的地址向后打印,遇到\0停止
🔸本题答案:POINT,ER,ST,EW
🔸代码如下:
#include <stdio.h> int main() { char* a[] = { "work","at","alibaba" }; char** pa = a; pa++; printf("%s\n", *pa); return 0; }
🚀结语:
如果对您有帮助的话,
不要忘记点赞+关注哦,蟹蟹
如果对您有帮助的话,
不要忘记点赞+关注哦,蟹蟹
如果对您有帮助的话,
不要忘记点赞+关注哦,蟹蟹