c语言指针查找问题,C语言指针和指针的指针的一个问题

关于指针和指针的指针问题,下面结合一个程序来看看。

1 #include

2 int main(void)

3 {

4

5         int i = 5, j = 6, k = 7;

6         int *p1 = &i;

7         int *p2 = &j;

8         int **pp;

9

10         printf("p1=0x%x, value=%d\n", p1, *p1);

11         printf("p2=0x%x, value=%d\n", p2, *p2);

12         printf("p1=0x%x, p2=0x%x, pp=0x%x\n", &p1, &p2, &pp);

13         pp = &p1;

14         printf("pp=0x%x, *pp=0x%x, **pp=%d\n", pp, *pp, **pp);

15         *pp = p2;

16         printf("pp=0x%x, *pp=0x%x, **pp=%d\n", pp, *pp, **pp);

17         printf("p1=0x%x, value=%d\n", p1, *p1);

18         return 0;

19 }

上面代码第5行定义了三个局部变量,并初始化了,在x86架构下面,函数的调用会伴随有参数和变量的压栈行为,结合gdb调试看下在实际运行时的情况:

0818b9ca8b590ca3270a3433284dd417.png

我们将断点设置在main函数的第一条汇编指令位置

:第一条汇编指令是将调用main的函数的栈栈底部(rbp寄存器)压栈

:第二条指令是将main函数的栈帧的顶部(rsp寄存器)存入rbp寄存器中

:第三条指令是将rsp寄存器值减0x30字节大小,就是为main函数预留大小为0x30字节的栈空间

看下运行完上三条汇编指令后的栈空间内容:

0818b9ca8b590ca3270a3433284dd417.png

上图中最下面的红色框中就是main函数的栈空间的内容。接着汇编指令单步运行,看下i,j,k三个局部变量怎么压栈的。

:  将i=5变量压入rbp-0x8位置处,即0x7fffffffe578位置

: 将j=6变量压入rbp-0xc位置处,即0x7fffffffe574位置

: 将k=7变量压入rbp-0x4位置处,即0x7fffffffe57c位置

0818b9ca8b590ca3270a3433284dd417.png

如上图所示i.j.k都已入栈,此时栈空间布局如下:

0818b9ca8b590ca3270a3433284dd417.png

回到源代码看6行代码定义了一个指针p1,并将变量i的地址赋给它,对应的汇编代码为下图中红色框中的两行:

0818b9ca8b590ca3270a3433284dd417.png

: 将i所在的位置0x7fffffffe578赋给寄存器rax

: 将rax寄存器值压入rbp-0x18位置处,即0x7fffffffe568位置存的值是0x7fffffffe578

运行上面两条汇编指令之后,指针p1所在地址是0x7fffffffe568,指向变量i,即位置0x7fffffffe578处。

0818b9ca8b590ca3270a3433284dd417.png

同理第7行代码是定义了一个指针p2,并将变量j的地址赋给它,这里就不详细分析了。运行完第7行代码之后栈空间的布局如下:

0818b9ca8b590ca3270a3433284dd417.png

第8行定义了一个指向指针的指针pp,未做初始化。10~12行打印内容不作分析。

第13行pp = &p1是将p1的地址赋给pp,也就是pp指针指向p1所在地址0xffffe568

: 将-0x18(%rbp)地址,即p1所在位置赋给rax寄存器

: 将rax寄存器值压入rbp-0x28位置处,即0x7fffffffe558位置存的值是0x7fffffffe568

运行完上面两条汇编指令之后,pp所在地址为0x7fffffffe558,指向指针p1。

0818b9ca8b590ca3270a3433284dd417.png

此时栈空间的布局如下:

0818b9ca8b590ca3270a3433284dd417.png

运行第14行

printf("pp=0x%x, *pp=0x%x, **pp=%d\n", pp, *pp, **pp);

此时pp=0xffffe568,为pp指向的位置

*pp=0xffffe578, 为p1指向的位置

**pp=5,为p1指向位置的值

下面接着分析第15行*pp = p2做了什么?其对应的汇编代码如下:

0818b9ca8b590ca3270a3433284dd417.png

: 将-0x28(%rbp)即pp的值赋给rax寄存器,rax=0x7fffffffe568

: 将-0x20(%rbp)即p2的值赋给rdx寄存器,rdx=0x7fffffffe574

: 将rdx寄存器值存入rax值0x7fffffffe568位置处

0818b9ca8b590ca3270a3433284dd417.png

如上图所示,此时p1指向的是0xffffe574,也就是指向了变量j。此时栈空间的布局如下:

0818b9ca8b590ca3270a3433284dd417.png

行第14行

printf("pp=0x%x, *pp=0x%x, **pp=%d\n", pp, *pp, **pp);

此时pp=0xffffe568,为p指向的位置

*pp= 0xffffe574, 为p1指向的位置

**pp=6,为p1指向位置的值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值