刷爆指针笔试题

第一题

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

相关推荐
奋飞安全13 分钟前
初试js反混淆
开发语言·javascript·ecmascript
guoruijun_2012_414 分钟前
fastadmin多个表crud连表操作步骤
android·java·开发语言
CoderBob15 分钟前
【EmbeddedGUI】脏矩阵设计说明
c语言·单片机
浪里个浪的102416 分钟前
【C语言】计算3x3矩阵每行的最大值并存入第四列
c语言·开发语言·矩阵
Tmbcan16 分钟前
zkw 线段树-原理及其扩展
数据结构·zkw 线段树
@东辰24 分钟前
【golang-技巧】-自定义k8s-operator-by kubebuilder
开发语言·golang·kubernetes
2301_8017609324 分钟前
数据结构--PriorityQueue
数据结构
乐悠小码30 分钟前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列
史努比.32 分钟前
Pod控制器
java·开发语言
敲敲敲-敲代码41 分钟前
游戏设计:推箱子【easyx图形界面/c语言】
c语言·开发语言·游戏