从内存与汇编的角度理解C语言指针第02篇:pp、*pp、pp、**pp的区别(指向指针的指针)

编程入门 行业动态 更新时间:2024-10-10 07:23:43

从内存与汇编的角度理解C语言<a href=https://www.elefans.com/category/jswz/34/1768268.html style=指针第02篇:pp、*pp、pp、**pp的区别(指向指针的指针)"/>

从内存与汇编的角度理解C语言指针第02篇:pp、*pp、pp、**pp的区别(指向指针的指针)

本文是上一篇《从内存与汇编的角度理解C语言指针第01篇:p、*p、&p的区别》的续篇。

一、C程序

现有C程序如下:

int main(void) {int a = 1;      // 定义变量 a,值为 1int *p = &a;    // 定义指针 p,指向 aint **pp = &p;  // 定义指针 pp,指向 preturn 0;
}

二、对应的汇编代码

以上C程序中的第2~4行对应的汇编代码如下:

// 对应C代码:int a = 1;
mov    DWORD PTR [rbp-0xc],0x1    // 把数字1存放到内存单元[rbx-0xc]处,占4个字节// 对应C代码:int *p = &a;
lea    rax,[rbp-0xc]              // 把内存单元[rbx-0xc]的地址存入rax寄存器
mov    QWORD PTR [rbp-0x18],rax   // 把rax寄存器中的值存放到内存单元[rbp-0x18]处,占8个字节; 对应C代码:int **pp = &p; 
lea    rax,[rbp-0x18]             // 把内存单元[rbp-0x18]的地址存入rax寄存器
mov    QWORD PTR [rbp-0x8],rax    // 把rax寄存器中的值存放到内存单元[rbp-0x8]处,占8个字节

三、内存布局

内存布局如下:

变量变量地址内存地址内存值
pp&pp0x61fe180x61fe08
p&p0x61fe080x61fe14
a&a0x61fe140x01

四、pp*pp&pp**pp的区别


在本例中:

  1. a:变量a,值是1
  2. p:指针变量p,值是变量a的地址0x61fe14
  3. *p:指针变量p的所指变量a的值,是1
  4. &p:指针变量p的地址0x61fe08
  5. pp:指针变量pp,值是指针变量p的地址0x61fe08
  6. *pp:指针变量pp的所指变量p的值,而p的值在上面第2行有说明,即变量a的地址0x61fe14。可以看出*pp == p
  7. &pp:指针变量pp的地址0x61fe18
  8. **pp:为方便理解,我们加上括号,得到:*(*pp)*pp在第6行已经有说明,*pp == p ,代入*(*pp),则*(*pp) == *p,而*p在第3行有说明,它是指针变量p的所指变量a的值,也就是1

五、对于*的理解

按照《C程序设计语言(K&R)第2版》书中的说明:“一元运算符*是间接寻址或间接引用运算符。当它作用于指针时,将访问指针所指向的对象。”
在执行*p时,CPU执行了2步操作:
  1. 通过p的地址去内存中查找,得到了p的内容,p的内容又是一个地址(a的地址)
  2. 通过a的地址去内存中查找,得到a的值。需要2步操作才取得了数据,因此是间接寻址
因此*可以理解为:CPU通过间接寻址去取值。
这里需要说明,间接寻址取值,取到什么就是什么,这个值是地址还是数据是由我们程序员来决定的。比如对于**pp来说,第1步得到的是地址,第2步得到的也是地址,第3步得到的才是数据。

参考资料:寄存器直接寻址和间接寻址的区别?

更多推荐

从内存与汇编的角度理解C语言指针第02篇:pp、*pp、pp、**pp的区别(指向指针的指针)

本文发布于:2024-03-09 08:13:17,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1724427.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:指针   角度   区别   内存   语言

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!