指针面试笔试题练习 |
您所在的位置:网站首页 › spark基础笔试题及答案 › 指针面试笔试题练习 |
前言
🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:介绍c语言中有关指针更深层的知识. 金句分享: ✨星光不问赶路人,✨ ✨时光不负有心人。✨ 目录 前言笔试题1文字解释1:图解1: 笔试题2文字解释2: 笔试题3文字解释3:图解3: 笔试题4文字解释4: 笔试题5文字解释5:图解5: 笔试题6图解6: 笔试题7笔试题8(难度提升)分析1: ** ++cpp分步动态图解1: 分析2:*-- * ++cpp + 3分步动态图解2: 分析3:*cpp[-2] + 3分步动态图解3: 分析4:cpp[-1][-1] + 1分步动态图解4: 笔试题1题目1: #include 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,5 文字解释1:a是数组名,类型为int[5],则&a类型为int(*)[5],当&a+1时,一次会跳过5个整形数据,则指向a数组的最后一个元素的后一个位置,ptr - 1刚好指向a数组的最后一个元素,解引用(星号)就会得到整形数字5. a+1表示数组的第二个元素,所以解引用得到整形数字2. 图解1: 笔试题2不了解指针运算的可以点击这里哦! [传送门] 考点:指针+1,跳过的步长 题目2: #include //已知结构体Test的大小是20字节 struct Test { int Num; char* pcName; short sDate; char cha[2]; short sBa[4]; }*p; int main() { p = (struct Test*)0x100000;//假设p 的值为0x100000。 printf("%p\n", p + 0x1);//0x100020 printf("%p\n", (unsigned long)p + 0x1);//0x10 printf("%p\n", (unsigned int*)p + 0x1); return 0; }运行结果: 00100014 00100001 00100004 文字解释2:p + 0x1: 因为p是一个结构体指针,结构体的大小是20个字节,所以p+0x1会跳过20个字节,20转化为16进制表示是14. (unsigned long)p + 0x1: 这里需要注意的是,这里将p强制转化为无符号长整形,并不是无符号长整形指针,所以,+0x1只是正常的+1,就好比1+1=2,就只是变量之间的正常+1. (unsigned int*)p + 0x1 将p指针强制转化为无符号整形指针,因为无符号整形是四个字节,则+0x1会跳过四个字节,转化为16进制4. 笔试题3题目3: 环境:x86 小端环境 #include 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,2000000 文字解释3:ptr1 因为&a + 1表示跳过a数组,指向a数组最后一个元素的后一个位置. ptr1[-1]等价于 *(ptr-1),即解引用得到数组的最后一个元素4. ptr2:需要注意的是,向后偏移了一个字节. (int)a + 1,表示将a强制转化为int整形,整形+1就是正常的+1,则会向后偏移一个字节, (int*)((int)a + 1)再强制转化为整形指针,在小端存储模式下,会从首元素1(占四个字节)的第二个字节开始,向后读取四个字节(红色框框).这时按16进制打印出来就是2000000了. 图解3: 笔试题4 #include int main() { int a[3][2] = { (0, 1), (2, 3), (4, 5) }; int* p; p = a[0]; printf("%d", p[0]); return 0; }运行结果: 1 文字解释4:是不是感觉很奇怪,不应该是0吗? a[0]表示二维数组的第一行的数组名,那么p[0]就等价于a[0][0],就是0呀. 实际本题考察重点是在逗号表达式. ? ? ? 这才是二维数组的初始化:用的是{} int a[3][2] = { {0, 1 }, {2, 3}, {4, 5} }; 而上面用的是(),则编译器会认为是逗号表达式,只保留后面的结果. 等价于: int a[3][2] = { (0, 1), (2, 3), (4, 5) }; ====== int a[3][2] = { 1, 3, 5 }; 故二维数组的初始化结果是 1 3 5 0 0 0 第一行第一个元素是1.做题要仔细哦,掉坑里了. 笔试题5题目: #include 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; }运行结果: FFFFFFFC,-4 文字解释5:a是二维数组的数组名,类型是int ()[5],一次跳过五个整形 p是一个数组指针,类型是int()[4],一次跳过四个整形, a[4][2]与p[4][2]之间差了4个字节,即&p[4][2] - &a[4][2]=-4; -4按"%p"形式打印.会认为内存中的数据是内存.-4在内存中是按补码存的. -4 1000 0000 0000 0000 0000 0000 0000 0100原码 1111 1111 1111 1111 1111 1111 1111 1011反码 1111 1111 1111 1111 1111 1111 1111 1100补码 转化为16进制表示地址后:F F F F F F F C 图解5: 笔试题6题目: #include 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: 笔试题7题目: #include int main() { char* a[] = { "work","at","alibaba" }; char** pa = a; pa++; printf("%s\n", *pa); return 0; }运行结果: at 解释: a是一个字符指针,类型是char*,a+1会跳过一个char类型. pa是一个二级指针,类型是char**,pa+1会跳过一个char*.即指向数组的第二行,%s从该地址处向后打印直到遇到’\0’. 动图解析: 笔试题8(难度提升) #include int main() { char* c[] = { "ENTER","NEW","POINT","FIRST" }; char** cp[] = { c + 3,c + 2,c + 1,c }; char*** cpp = cp; printf("%s\n", **++cpp); //1 printf("%s\n", *-- * ++cpp + 3); //2 printf("%s\n", *cpp[-2] + 3); //3 printf("%s\n", cpp[-1][-1] + 1); //4 return 0; }运行结果: POINT ER ST EW 解释分析: 需要注意的是,当进行自增(++)或者自减(–)时,会真正改变指针的值,从而影响后面的语句.而加减整数或者访问元素([ ])并不会改变指针本身.并不会对后面的语句造成影响. c是一个字符指针,+1会跳过一个字符(1字节). cp是一个指向一级字符指针的二级指针,+1可以跳过一个char*类型指针. cpp是一个指向cp的三级指针,+1会跳过一个二级指针. 分析1: ** ++cpp原始状态图: ++cpp会跳过一个二级指针,并且是真正改变cpp指针的内容, 即cpp会指向cp的第二个元素,c+2 *++cpp表示得到c+2的地址 **++cpp表示得到c+2的值,即P的地址,按%s打印会得到,POINT. 分步动态图解1: 分析2:*-- * ++cpp + 3注意!!! cpp由于1的改变,现在指向的是c+2. 原始图2: ++cpp会使cpp指向c+1(cp的第二个元素). *++cpp得到c+1的地址 - - *++cpp表示c+1的地址–,会会指向c *-- * ++cpp 会得到c的地址 *-- * ++cpp + 3表示指向E 按%s打印会打印ER. 分步动态图解2: 分析3:*cpp[-2] + 3注意!!! 因为2的改变,此时cpp指向的是c+1. 图三原始图: cpp[-2]等价于*(cpp-2),表示访问cpp指向的元素,往前找两个位置,即cp的第一个元素,c+3, *cpp[-2]解引用得到c+3的地址. *cpp[-2] + 3,表示指向c+3的第3个字符. 按%s打印,结果为ST 分步动态图解3: 分析4:cpp[-1][-1] + 1注意!!! 3只是[-2]访问,并没有改变cpp本身. 原始图四:(与图三一样) cpp[-1]等价于*(cpp-1),表示访问cpp指向的内容的前一个,即c+2(cp的第二个元素). cpp[-1][-1]表示访问c+2地址的前一个,即N地址处. cpp[-1][-1] + 1表示从N地址的下一个地址,E开始. 按%s打印是EW 分步动态图解4:这次的指针面试题练习就讲到这里,希望对各位有所帮助. 886. |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |