• [C]这些指针笔试题你都学废了吗?


    作者 华丞臧.
    专栏【C语言】
    各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞+收藏+关注)。如果有错误的地方,欢迎在评论区指出。
    在这里插入图片描述

    笔试题1

    int main()
    {
        int a[5] = { 1, 2, 3, 4, 5 };
        int *ptr = (int *)(&a + 1);
        printf( "%d,%d", *(a + 1), *(ptr - 1)); // 2   5
        return 0;
    }
    //程序的结果是什么?
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    程序的结果是2,5
    需要注意的是&a取出的是整个数组的地址&a+1表示跳过整个数组的地址指向数组后面的空间。
    在这里插入图片描述

    在这里插入图片描述

    笔试题2

    //由于还没学习结构体,这里告知结构体的大小是20个字节
    struct Test
    {
     int Num;
     char *pcName;
     short sDate;
     char cha[2];
     short sBa[4];
    }*p;
    //假设p 的值为0x0000000。 如下表表达式的值分别为多少?
    //已知,结构体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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    程序结果是0x00 00 00 14,0x00 00 00 01,0x00 00 00 04
    在这里插入图片描述
    已知结构体大小为20个字节,p是结构体指针那么p+1就表示跳过一个结构体大小的地址指向其后面的地址。
    在这里插入图片描述

    笔试题3

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    程序的结果是4,2000000
    在这里插入图片描述
    显然ptr1是跳过a数组指向a数组后面的地址,ptr1[-1]相当于*(ptr1-1)所以ptr1[-1]会指向a数组最后一个元素4

    ptr2 = (int *)((int)a + 1);
    //(int)a+1  把a数组首元素地址强转为整型再加一
    //(int*) 把((int)a + 1)强转为整型指针
    //ptr2指向的是a数组首元素地址的下一个字节
    
    • 1
    • 2
    • 3
    • 4

    我的系统是小端字节序存储,根据小端存储数据的方式,a数组首元素在内存中地址从低到高存储的是 01 00 00 00 ,可以知道*ptr2中存储的是 02 00 00 00
    在这里插入图片描述

    笔试题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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    程序结果是1.
    在这里插入图片描述
    p中存放的是a数组第一行的地址 p[0] 等价于 p[0][0],也就是第一行第一个元素;a[0][0] = = 0。逗号表达式的值等于逗号表达式中最后一个式子的值。
    在这里插入图片描述

    笔试题5

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    程序的结果是0x ff ff ff fc ,-4
    在这里插入图片描述

    从下图可以看出,&p[4][2] - &a[4][2] = -4
    在这里插入图片描述

    -4的二进制原码为:1000 0000 0000 0000 0000 0000 0000 0100
    -4的二进制反码为:1111 1111 1111 1111 1111 1111 1111 1011
    -4的二进制补码为:1111 1111 1111 1111 1111 1111 1111 1100
    内存中存放的是补码,而&p是以地址的形式打印,所以打印的是:
    二进制:1111 1111 1111 1111 1111 1111 1111 1100
    16进制:ff ff ff fc

    笔试题6

    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)); //10   5
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    程序结果是10,5
    在这里插入图片描述

    (&aa+1)表示跳过整个数组指向数组地址后面的地址。
    *(aa+1)取出第二行的地址,第二行的地址就是第二行首元素的地址即a[1][0]的地址。
    在这里插入图片描述

    笔试题7

    #include 
    int main()
    {
     char *a[] = {"work","at","alibaba"};
     char**pa = a;
     pa++;
     printf("%s\n", *pa); //at
     return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    程序结果是"at"。
    在这里插入图片描述
    pa是字符指针,那么我们要知道字符指针数组a当中存储字符串时存储的是字符串中首字母的地址;所以当pa指向a时,pa++跳过的是一个一级字符指针,此时pa中存储的是a[1]的地址,*pa == a[1] == "at"
    在这里插入图片描述

    笔试题8

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    程序结果是POINT、ER、ST、EW
    在这里插入图片描述

    注意

    1. 指针后面加[N]表示指针加上N再解引用。
    2. 前置和后置 加减 会永久改变指针变量的值。

    在这里插入图片描述

    int arr[] = {1,2,3,4,5];
    int* p = arr;
    //p[3] = *(p+3) = arr[3];
    
    • 1
    • 2
    • 3

    解析:
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    深入浅出理解SVM支持向量机算法
    【python后端】- 初识Django框架
    php脚本执行timeout
    【开源】SpringBoot框架开发用户画像活动推荐系统
    数学建模之线性规划(含MATLAB代码)
    GPU并行计算- 基础知识
    【深度学习】 Python 和 NumPy 系列教程(十九):Matplotlib详解:2、3d绘图类型(5)3D等高线图(3D Contour Plot)
    在 macOS 上安装 Docker
    数据结构系列学习(五) - 双向链表(Double_Linked_List)
    Redis 如何实现库存扣减操作和防止被超卖?(荣耀典藏版)
  • 原文地址:https://blog.csdn.net/qq_59456417/article/details/127495609