刷爆指针笔试题

第一题

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;
}

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


【解析】

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

p表示的是首元素的地址,即第一行的地址 ,而p[0]表示的是第一行的第一个元素,即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[]数组的首元素地址,a[0]的地址

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

所以打印*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

相关推荐
cdut_suye2 分钟前
全面剖析 Linux 进程管理与 PCB 机制
java·linux·运维·服务器·c++·人工智能·python
仟濹6 分钟前
【算法 C/C++】二维前缀和
c语言·c++·算法
Chenyu_31011 分钟前
04.基于C++实现多线程TCP服务器与客户端通信
linux·服务器·网络·c++·tcp/ip·算法·visualstudio
待什么青丝28 分钟前
【TMS570LC4357】之工程创建
c语言·单片机
音视频牛哥34 分钟前
C++20之2025年上桌我坐哪儿?
c++·编程语言·ai 编程
不爱学习的小枫1 小时前
scala的集合
开发语言·scala
梦醒沉醉1 小时前
Scala的初步使用
开发语言·后端·scala
小白学大数据1 小时前
Fuel 爬虫:Scala 中的图片数据采集与分析
开发语言·爬虫·scala
贩卖纯净水.1 小时前
《React 属性与状态江湖:从验证到表单受控的实战探险》
开发语言·前端·javascript·react.js
JouJz1 小时前
Java基础系列:深入解析反射机制与代理模式及避坑指南
java·开发语言·代理模式