刷爆指针笔试题

第一题

cpp 复制代码
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表示整个数组的地址,+1表示跳过整个数组

它属于数组指针 ,需要强转成int*类型的指针才能赋给ptr

而ptr属于整型指针 ,-1跳过四个字节,也就是说(ptr-1)指向对应数字5的位置,解引用之后得到数字5

第二题

cpp 复制代码
struct Test{ 
    int Num; 
    char *pcName; 
    short sDate; 
    char cha[2]; 
    short sBa[4];
}*p;

//假设 p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节

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跳过20个字节

注意用16进制表示****,0x100000+0x000014=0x100014


p转换成unsigned long类型时正常计算0x100000+0x000001=0x100001


int*类型指针+1跳过4个字节,所以计算方式为0x100000+0x000004=0x100004

第三题

cpp 复制代码
int main()
{    
    int a[4] = { 1, 2, 3, 4 };      
    int *ptr = (int *)((int)a + 1);    
    printf( "%x", *ptr);    
    return 0;
}

先自己思考一下,然后再看解析哦


【解析】

a表示首元素地址,转换成int类型再+1,相当于只是跳过一个字节

我们看该数组再内存中的存储方式(小端存储)

低地址 高地址

++01 00 00 00++ 02 00 00 00 03 00 00 00 04 00 00 00

原先首地址读取的内容 0x1

低地址 高地址

01 ++00 00 00 02++ 00 00 00 03 00 00 00 04 00 00 00 移动一个字节后

变成0x2000000

所以输出的内容就是0x2000000

第四题

cpp 复制代码
#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;
}

先自己思考一下,然后再看解析哦(此题很坑!)


【解析】

括号仅仅表示的是优先运算,而不是表示数组每行的分隔(花括号才表示二维数组中的分行),所以此数组可以简化为a32={1,3,5}

p表示的是首元素的地址,即第一行的地址 ,而p0表示的是第一行的第一个元素,即1

第五题

cpp 复制代码
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是二维数组,也可以理解为一个数组指针int(*)5

p是一个数组指针int(*)4

p = a; //表示将a的首元素地址赋给p

a+1跳过5个整型,而p+1跳过4个整型

为了方便理解,我画了个方便理解的图(此类题目非常建议画图)

注:二维数组在内存中也是连续存放的

先看%d打印的,两个地址相减表示的是两者之间的元素个数,而小地址---大地址为负数,据图可得结果为-4

%p是打印地址,而内存中的存储的补码就是地址

即打印结果为-4的补码0xFFFFFFFC

第六题

cpp 复制代码
#include <stdio.h>
int main() 
{
    char *a[] = {"work","at","alibaba"};
    char**pa = a;
    pa++;
    printf("%s\n", *pa);
    return 0; 
}

先自己思考一下,然后再看解析哦


【解析】

a\[\]是一个字符指针数组,存放的是三个字符串的首地址信息

而pa是二级指针,指向的是a\[\]数组的首元素地址,a0的地址

pa++表示的是pa指向a\[\]数组的下一个地址,即a1的地址

所以打印*pa即表示打印a\[\]数组中的第二个元素,即"at"

第七题

cpp 复制代码
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移到下一位,然后按照连线就可以推出两次解引用后得到的是POINTER

第二问:

先算自增 ,(注意此处cpp是在第一问的基础上变化的),得在cp+2的位置上,然后自减 得c,最后算+3,得ENTER的后两位:ER

第三问(思路与前面类似)

cpp-2等价于*(cpp-2),也就是指向cp的位置 ,存的是c+3的地址 ,解引用后得FIRST的首地址,最后+3得ST

第四问:

注意此时cpp指向的是cp+2,因为上一问并没有改变cpp的内容,cpp-1就是指cp+1的位置,而再算后面的-1就是指c+2-1=c+1 ,最后算+1,所以得NEW的后两位EW

相关推荐
言乐63 分钟前
Python概括后端原理
开发语言·python·django·virtualenv·pygame
无名猿15 分钟前
拷贝构造与拷贝赋值:调用时机、深浅拷贝与复制消除
c++·内存管理·现代c++·踩坑记录
@大迁世界21 分钟前
JEV RAG:更高效的 RAG 系统解决方案?
开发语言·rust
大侠归来1 小时前
C语言素数判断:从入门到进阶
java·c语言·算法
朝朝辞暮i1 小时前
C++ 第一阶段总结:从零基础到 ROS2 前置语法
开发语言·c++·算法
朝朝辞暮i1 小时前
C++ 第 25 课:getter / setter + this
java·javascript·c++
2601_962885721 小时前
如何用 Python 回测定投策略(定期定额 DCA)?(和一次性买入对比)
开发语言·人工智能·python
H.莓飛1 小时前
【数据结构】链表_OJ题
linux·数据结构·算法·链表
周杰偷奶茶1 小时前
【JavaSE】类和对象基础
java·开发语言
All for pursuit.2 小时前
【回溯-4】46.全排列
数据结构·c++·算法·leetcode