C语言指针和指针的指针的一个问题

本文通过一个具体的C语言程序示例,详细解析了一级指针与二级指针的工作原理及其相互间的关系,包括如何使用指针来操作变量及其它指针。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

  1 #include <stdio.h>

  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调试看下实际运行时的情况


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

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

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

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


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


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

<+8>:  i=5变量压入rbp-0x8位置处,0x7fffffffe578位置

<+15>: 将j=6变量压入rbp-0xc位置处,0x7fffffffe574位置

<+22>: 将k=7变量压入rbp-0x4位置处,0x7fffffffe57c位置


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

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


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

<+33>: rax寄存器值压入rbp-0x18位置处,0x7fffffffe568位置存的值是0x7fffffffe578


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


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


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

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

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

<+135>: rax寄存器值压入rbp-0x28位置处,0x7fffffffe558位置存的值是0x7fffffffe568


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


此时栈空间的布局如下:

运行第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做了什么?其对应的汇编代码如下:


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

<+181>: 将-0x20(%rbp)p2的值赋给rdx寄存器rdx=0x7fffffffe574

<+185>: rdx寄存器值存入rax值0x7fffffffe568位置处




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

行第14行

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

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

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

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值