reverse_xiaoyu

忘记并不可怕,可怕的是你从来就都不知道!

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

指针(六)

  • 指向指针的指针:多级指针
  • 指向数组的指针:数组指针

一、指向指针的指针:多级指针 

1.*()和[]

  定义几个不同级别的指针类型的数据
1 char* p1;    
2 char** p2;    
3 char*** p3;    
4 char**** p4;    
5 char***** p5;    
6 char****** p6;    
7 char******* p7; 

1)*运算

  代码:
1 printf("%d",*p1);

  反汇编:

    
  结论:
     *运算的本质是取指针变量的值,利用这个值作为地址来寻址获取结果;
 
  代码:
1 printf("%d",*(p1+0));

  分析:

  根据指针类型的特性,p1+0所得的类型还是char*类型,
  并且所得的值要加上为去掉一个*后的类型的宽度乘以所加的数,而char的宽度是1,结果还是和原来一样;
 
  反汇编和*P1没有区别:
    
  结论:*(p1) ==*(p1+0)

 2)[]运算

  *(p1+0)可以用另一种写法:p1[0]
1 printf("%d",p1[0]);

  反汇编:

    
  分析:
    *(p1+0)和p1[0]生成的反汇编代码完全一样;
  结论:
    *(p1+0) == p1[0]
   代码:
1 printf("%d",*(p1+2));
2 printf("%d",p1[2]);

  反汇编:

    
  分析:
    *(p1+2)是用p1+2所得的值来寻址:p1+(char*去掉一个*后的类型的宽度也就是char=1)x2;
    *(p1+2)的反汇编和p1[2]完全一样;
  结论:
    *(p1+2) == p1[2]
 

3)多级指针

  p2的类型是char**,也就是二级指针;
  凡是带*的类型的变量都可以进行*运算;
  *运算后的类型为原来的类型去掉一个*;
  代码:
1 printf("%d",*(*(p2)));

   反汇编:

  
  分析:
    取p2的值,利用p2的值寻址,利用地址处的值为地址再次寻址;
 
  代码:
1 printf("%d",*(*(p2+0)+0));

   反汇编:

  
  分析:
    *(p2+0) == *p2,经过*计算后类型变化:char**    ->char*;
    *(*p2+0) == *(*p2),因为*p2位char*类型,而char*类型的特性,加上一个整数等于加上去掉一个*后的类型的宽度乘以整数,也就是0,结果还是*p2;
  结论:
    *(*(p2+0)+0) == *(*p2)
      代码:
1 printf("%d",*(*(p2+1)+2));
2 printf("%d",p2[1][2]);

   反汇编:

  
  
  分析:
    p2是char**类型,根据指针类型的特性,p2+1相当于加上去掉一个*的类型的宽度乘以1;
    也就是char*的宽度乘以1,又因为所有带*的类型宽度都是4,因此生成的反汇编寻址时为[eax+4];
    同理,第二次寻址时的反汇编是[ecx+2];
    *(*(p2+1)+2)生成的反汇编和p2[1][2]完全一样;
  结论:
     *(*(p2+1)+2) == p2[1][2];

 4)总结:                

1 *(p + i) = p[i]                
2 *(*(p + i) + k) = p[i][k]                
3 *(*(*(p + i) + k) + m) = p[i][k][m]                
4 *(*(*(*(*(p + i) + k) + m) + w) + t) = p[i][k][m][w][t]  

 

  *() 与 []可以相互转换    
 

2.实例

1 char** p;
2  
3 printf("%d",*(p+1)[2]);
4 printf("%d",*(*(p+1)+2));

 

 
  反汇编:
    
  分析:
    *(p+1)[2] != *(*(p+1)+2)
    因为[]的运算优先级要高于*,先计算p+1移动4个字节;
    然后计算(p+1)[2],相当于以p+1指向的地址作为首地址的数组,移动2*4=8个字节,所以为[eax+c];
    最后做*运算;
    也就是说:*(p+1)[2] ==  *(*(p+1+2));

二、指向数组的指针:数组指针

 

  结构体指针    ->存了一个地址,该地址指向一个结构体;
  指针的指针    ->存了一个地址,该地址指向一个指针;
  数组指针    ->存了一个地址,该地址指向一个数组;   
 

1)数组指针的特性

  和普通指针的特性差不多:
  •     宽度为4;
  •     可以++、--;
  •     可以加减一个整数;
 
2)使用数组指针
 
  利用指针数组遍历:
 

3)数组指针和指针数组的区别

  int *p[5] 与 int (*p)[5]  有什么区别?
原因:
    [] 的优先级高于*  所以先组合成p[5]数组 再由int *说明 数组存储的类型 == int* p[5];
    () 的优先级高于[] 所以*先p先组合成指针 再由int[5]说明数组的宽度
posted on 2020-03-12 17:33  Reverse-xiaoyu  阅读(195)  评论(0编辑  收藏  举报