菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
438
0

1.指针的那些事

原创
05/13 14:22
阅读数 75285

  学逆向最重要的基础就是c/c++,而学c其实就是学指针,指针的重要性不言而喻,而阻挡大家的指针,其实并没有那么难理解,我们一起看看吧!

  内存模型

  学习指针前必须了解内存是个什么样子的,不然无法理解指针的概念

  |               a               |  0x0

  |               b               |  0x4

  |               c               |  0x8

  |               d               |  0xC

  |               e               |  0xF

    这就是一个基本的内存模型,每一行代表一个内存,格内代表内存,格内内容代表存入的值,格后方标号代表内存地址

  我们每次在申请变量时,如 int x=0x15;  其实是在内存中申请了一段空间,int代表申请四字节,x是变量名,0x15是值。

  对应上图中第一行,在格内放入变量名为x、值0x15的一个四字节变量。

  这里知识点出现了:在32位系统下,一个内存地址就是四个字节,所以我们申请一个int,相当于占了一整行,也就是一个内存空间,而内存空间的地址为编号0x0。

    它在内存里长这样:

    |      00    00   00    15         |  0x0        (其实此处涉及大小端序的问题,但是为了方便理解我们先以大端序为例)

  理解了这个,我们再来想一下,如果我申请的是 char x=0x15; 会怎么样呢?

  没错,因为char只占一个字节,第一行没被占满,其实内存是这样的:

        |      15    00   00    00         |  0x0  

    本例后面这三个地址是没有被分配的,而上例中4个字节均被分配了。

  好的,到这大家其实已经把指针学明白了。嗯?你不都没提指针吗?

  对,指针就是存放标号的变量而已,值就是格子右边的0x0。至于指针有类型只不过是它每移动一次是几个字节而已,这个放到下面讲。

  此处你只需要记住,指针是一个变量,它的值是地址的值就好了。

 

  数组与指针

  在c语言中数组其实与指针有着千丝万缕的联系。

  首先我们来看一段代码:

   

  首先这里有一个变量a和一个数组b,其中pa是a的指针(&符号是取地址的意思),pb是b的指针。

  到这里细心的小伙伴应该发现了,你不是说pb是b的指针吗,为什么不加取地址符号?这里就是我们学习指针要过的第一个坎:数组名其实就是指针!

  我们先不看b和pb,大家都知道pa其实是a的地址,而通过指针访问a的写法为*pa,那pa+1呢?没错,是a的地址加上4个字节,同理访问其值的写法为*(pa+1)。

   

  那有了这个基础,我们先来看一下b的访问,如果你想取数组的第一个值,你得写b[0],

  第二个b[1]。如果用pb访问呢?分别为*pb,*(pb+1)。嗯?到这里是不是发现了什么?没错!就是你想的那样。数组的访问其实是指针加偏移的形式访问的,所以说数组名其实就是指针!

  我们打出b和pb:

   

  到这里就完了吗?怎么可能,到这完了肯定有大佬喷我了。那我们忽略了哪里呢?就是&b和&b+1到底指向哪里,我们打出来看看:

   

  聪明的小伙伴已经明白了吧,&b时指向的还是数组b的第一个数据的首地址,而整个数组b指针的加1,要加上整个数组大小进行地址偏移(本例中是5个地址偏移)。

  最后我们再从汇编层面看看数组访问时的行为:

   

  没错吧!其实底层的行为就是基址加偏移访问的。

  

  遗留问题补充

  到这里,指针基本就学完了,我们来解决下遗留问题:

  一、指针的类型

  从上面例子中不难看出,我们一直使用的是int*类型的指针,而它每次加1就会移动四个字节。如果我们换成char*类型的呢?

  没错那每次就移动一个字节,当然这样的话就会遇到一些问题,但是这些问题是可以预测的,

  当然会涉及到大小端序,在此处就不讨论了,大家感兴趣自己去试试就好了

  二、指针数组和数组指针

  这个其实很多人分不清,但是没必要。这只是个文字游戏而已,我区分他们的方法很简单,就是中间加个的。

  "的"字后面出现的是关键:指针的数组,表名它是数组,而每个数组的内容是由指针构成的。

              数组的指针,表名它是指针,是指向数组的指针,上面已经提到了,就是那个加1时会移动整个数组长度的指针。

  三、函数的指针

  函数指针也没啥新鲜的,依旧是指针。只是定义时比较特别需要typedef。它的关键在于可以直接通过指针加参数的形式调用。

  它可以传参调用函数,这是重点也是难点,这样一来它的应用就比较灵活了,因为你可以通过一个指针调用不同函数。

  这也是高级编程中经常使用的方式,如果有兴趣可以自行研究。

 

 

  本期的内容就到这里了,大家有什么建议和问题一定要骚扰我哈,也欢迎大家加微信讨论,联系方式在我的博客--杂七杂八--置顶的那篇文中。

 

发表评论

0/200
438 点赞
0 评论
收藏
为你推荐 换一批