• 从指针开始变强(四)之超级详细笔试题(二)



    前言

    发现了新的整理解释的方法–代码块
    真的好用啊


    一、练习题

    1.练习1

    #include<stdio.h>
    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
    • 9
     1. &a+1 
          a作为数组名 取地址后 数组名为整个数组的地址
                   &a+1为跳过整个数组下一块空间的地址
            %x代表最终结果以16进制输出
            而在内存中以16进制表示的
            VS中在内存以小端存储的
            1  ---  00   00  00   01
            2   --- 00   00  00   02
            3   --- 00   00  00   03
            4  ---  00   00  00   04
            小端存储是以低字节位放在低地址处 高字节放在高地址处
            内存中表示为
            01 00 00 00   02 00  00 00   03 00 00 00   04 00 00 00
            ptr1[-1]等价于 *(ptr1-1)
            整形指针减一跳过4个字节 又因为是整形指针取4个字节
             即 04 00  00  00
            转换为正常表示为 00 00  00  04
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
       2.   (int)a+1 
           a作为数组名 没有单独放在sizeof内部 也没有取地址
           数组名作为首元素地址 即1的地址
           强制转换为整形  +1:    a为 0x20--->32
                       32+1------>33
                       33------->0x21
                    字节数加1
     内存中表示为
            01 00  00  00   02 00 00 00    03 00 00 00   04 00 00 00
            
            a原来为  01 00  00  00
             *ptr2为 00  00 00  02
            *ptr2转换正常为 02 00 00 00
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.练习2

    #include<stdio.h>
    int main()
    {
     int a[5][5];
     int(*p)[4];
     p=a;
     printf("%p,%d",&p[4][2]-&a[4][2],&p[4][2]-&a[4][2]);
     return 0;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
     a为二维数组的数组名 没有单独放在sizeof内部 也没有取地址
      数组名作为首元素地址  二维数组的首元素地址为第一行的地址
      应用数组指针接受即 int(*)[5]  而p虽然只能存放4个元素
      但依旧可以传进去  p+1 跳过4个整形  a+1跳过5个整形
      a[4][2]为第5行第三个元素 
      p[4]作为第五行的数组名  取地址后 数组名为整个第五行的元素
      即 &p[4][2]为 p本身跳跃的第五行第三个元素的地址
     
     需要注意的是 数组随着下标的增大 地址由低变高
     故   p[4][2]所在为低地址
          a[4][2]所在为高地址
          &p[4][2]-&a[4][2] 为负
          地址相当于指针  指针-指针为两者之间的元素个数 即 4
           结果为 -4
           
         -4  原码 10000000 00000000 00000000 00000100
             反码 11111111 11111111 11111111 11111011
             补码 11111111 11111111 11111111 11111100
             而地址在内存中 以补码形式表现出来
             即 11111111 11111111 11111111 11111100
              转换成16进制
                 FF       FF        FF     FC 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述


    3.练习3

    #include<stdio.h>
    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",*(ptr1-1),*(ptr2-1));
    return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
      1. &aa   aa作为整个二维数组的数组名 取地址后
         数组名作为整个二维数组的元素
         取得是整个二维数组的地址
         &aa+1 为跳过整个数组下一块空间的地址
         *(ptr1-1) 整形指针减一  跳过4个字节 
         即指向 10  
         结果为10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
      2. *(aa+1)  aa作为二维数组的数组名
         没有单独放在sizeof内部 也没有取地址
         数组名作为首元素地址 二维数组的首元素地址是 第一行的地址
         
          aa+1 为第二行的地址  解引用后为代表第二行的元素
          第二行的元素可以看作是第二行的数组名
          数组名 没有单独放在sizeof内部 也没有取地址
          数组名为首元素地址  即6的地址
          *(ptr2-1) 整形指针减一  指针向左移移位
          即 5
          结果为5
           
           
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4.练习4

    #include<stdio.h>
    int main()
    {
    char*c[]={"ENTER","NEW","POINT","FIRST"};
    char**cp[]=(c+3,c+2,c+1,c};
    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
    • 12
    1. **++cpp
       cpp作为三级指针 接收cp
       cp为一个二级指针数组  cp作为数组名 没有单独放在sizeof内部
       也没取地址  cp数组名作为首元素的地址 即c+3的地址
       ++cpp  cpp指向c+2
       **++cpp  cpp作为c+2的地址  c+2本身指向POINT
       即为POINT
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    2. *-- * ++cpp+3
     因为运算符优先级问题 
     应先算  ++  再算解引用 再算 --  再算解引用  最后再加3
     cpp在1中自加 指向c+2  
     再次++ 指向c+1 解引用找到c+1本身
     c+1本身-- 变成 c
       而不是cpp-- 所以cpp依旧指向c+1
       再次解引用 为ENTER  可以看作是E的地址
       +3向后三个单位 为ER
       即为ER
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    3. *cpp[-2]+3
      cpp[-2]等价于 *(cpp-2)
      即**9cpp-2)+3
      cpp在2中指向c+12指向 c+3
      解引用后 为c+3本身 
      再次解引用 为 FIRST  可以看作是F的地址
      +3 跳过3个单位 为 ST
      即 ST 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    4.
      cpp[-1][-1]+1
      cpp[-1][-1]等价于 *(*(cpp-1)-1)*(*cpp-1)-1)+13中没有自增自减 所以cpp依旧指向c+11 指向c+2
      解引用后 为c+2本身
      c+2本身减1 为 c+1
      解引用后为 NEW 可以看作是N的地址
      +1为向后跳过1个单位 
      即EW
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

  • 相关阅读:
    【第十篇】- Maven 引入外部依赖
    动态规划11(Leetcode931下降路径最小和)
    SOA和微服务是一回事吗
    2.4GHz、DA14530-00000FX2射频收发器/LSM6DSOTR 6 轴运动传感器/SKY66423-11射频前端 860MHz 至 930MHz
    Spring Bean中有哪些配置及常用属性呢?
    R语言绘图-3-Circular-barplot图
    【HCIP-Datacom】 IS-IS基础 ISIS动态路由协议配置(ISIS思维导图在底部)
    查询物流有多简单,具体步骤如下
    MBR30300VPT-ASEMI肖特基二极管MBR30300VPT
    军用FPGA软件 Verilog语言的编码准测之触发器、锁存器
  • 原文地址:https://blog.csdn.net/qq_62939852/article/details/125562901