刷爆指针笔试题

第一题

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

相关推荐
心态还需努力呀5 分钟前
把 Flameshot 编译进鸿蒙 PC:一次 Qt C++ 截图工具的源码级移植实战
c++·qt·harmonyos
白色的北极熊34 分钟前
c语言 输出菱形字符串
c语言·开发语言
科学实验家1 小时前
最小生成树:Prim,kruskal
数据结构·c++·算法
学习智者1 小时前
《玄》IDE v3.6.3重磅发布:全功能修复与性能飞跃
开发语言·c++·ide·算法·中文语言 玄
2402_882893861 小时前
C++异常:从概念到实践的一篇博客
c++·异常
奔跑吧树袋熊1 小时前
多租户隔离该做到哪一层:从连接池到 ORM 的取舍
开发语言·数据库·oracle·系统架构
大江东去浪淘尽千古风流人物1 小时前
【LoMa】局部特征匹配重访:从LoMa-B到旋转不变LoMa-R的架构与工程实践
开发语言·深度学习·计算机视觉·r语言·视觉定位·sfm·局部特征匹配
菜鸟~noob2331 小时前
【电子战】测向精度极限——克拉美-罗下限(CRLB)与误差分析【含matlab代码】
开发语言·matlab
m0_734571761 小时前
深入理解C++ 析构函数<二>析构顺序
开发语言·c++
T1mzhou1 小时前
ARM64 Linux 6.10 内核驱动(14):drivers/base/platform.c:板级设备主战场
linux·c语言·开发语言·arm开发