C语言中,Pointers to Pointers,即二级指针。

一级指针和二级指针的值都是指向一个内存单元:

  • 一级指针指向的内存单元存放的是源变量的值,
  • 二级指针指向的内存单元存放的是一级指针的地址。

下面,我们通过如下代码展示二级指针的底层实现:

#include <stdio.h>

int main(){
int a = 777;
int* b = &a;
int** c = &b;
*b = 888;
**c = 999;
printf("a=%d\n", a);
return 0;
}

假设:

  • 栈的基地址为0,即rbp寄存器指向0;
  • 栈的指针寄存器rsp指向地址为-32。

则,c语言语句**c = 999的底层实现过程如下图所示:

底层实现中,汇编语言首先找到c的值,通过c的值找到b的值,通过b的值找到a,并赋值999给a。

具体汇编代码如下:

         .file   "hlist.c"
.text
.section .rodata
.LC0:
.string "a=%d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp // rsp 减去 32
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movl $777, -28(%rbp) // 地址为-28处的存储单元的值为777,即a赋值为777
leaq -28(%rbp), %rax // 将-28地址(a的地址)赋给%rax
movq %rax, -24(%rbp) // 将-28(64位,8字节)值给地址为-24的存储单元
leaq -24(%rbp), %rax // 将-24地址(b的地址)赋给%rax
movq %rax, -16(%rbp) // 将b的地址赋值给地址为-16的存储单元
movq -24(%rbp), %rax // 将b的值(a的地址)赋值给%rax
movl $888, (%rax) // a = 888
movq -16(%rbp), %rax // 将c的值(b的地址)赋值给%rax
movq (%rax), %rax // 将b的值赋值给%rax
movl $999, (%rax) // a = 999
movl -28(%rbp), %eax
movl %eax, %esi
leaq .LC0(%rip), %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
movq -8(%rbp), %rdx
xorq %fs:40, %rdx
je .L3
call __stack_chk_fail@PLT
.L3:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
.section .note.GNU-stack,"",@progbits

C语言二级指针底层实现的更多相关文章

  1. C语言 二级指针内存模型①

    //二级指针第一种内存模型 #include<stdio.h> #include<stdlib.h> //说明:①:类似于int a[5]={0},数组名a是一维数组a中首元素 ...

  2. 真正明白C语言二级指针(转载)

    指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也经常用到:比如说对于字符串的处理,函数参数的“值,结果传递”等,对于二级指针或者多级指针,我想理解起来也是比较容易的,比如二级指针就是指向指针的 ...

  3. C语言二级指针(指向指针的指针)

    转载:http://c.biancheng.net/cpp/html/85.html 指针可以指向一份普通类型的数据,例如 int.double.char 等,也可以指向一份指针类型的数据,例如 in ...

  4. 真正明白c语言二级指针

    指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也经常用到:比如说对于字符串的处理,函数参数的“值,结果传递”等,对于二级指针或者多级指针,我想理解起来也是比较容易的,比如二级指针就是指向指针的 ...

  5. C语言 二级指针内存模型混合实战

    //二级指针内存模型混合实战 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #i ...

  6. C语言 二级指针内存模型③

    //二级指针内存模型③ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #incl ...

  7. C语言 二级指针内存模型②

    //二级指针第二种内存模型 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #incl ...

  8. c语言二级指针内存模型

    第一种: 指针数组作为输入参数 char *myArray[] = {"aaaaaa", "ccccc", "bbbbbb", " ...

  9. C语言二级指针间接赋值

    重要意义:间接赋值的意义,实现了模块的功能划分,实现了软件作品的分层,使得模块接口和信息系统得以实现. 所谓二级指针就是指向指针的指针,其声明形式如下 int *p=NULL int **p1=NUL ...

随机推荐

  1. LeetCode_350. Intersection of Two Arrays II

    350. Intersection of Two Arrays II Easy Given two arrays, write a function to compute their intersec ...

  2. new (std::nothrow) 与 new

    普通new一个异常的类型std::bad_alloc.这个是标准适应性态. 在早期C++的舞台上,这个性态和现在的非常不同:new将返回0来指出一个失败,和malloc()非常相似. 在内存不足时,n ...

  3. AI - TensorFlow - 示例04:过拟合与欠拟合

    过拟合与欠拟合(Overfitting and underfitting) 官网示例:https://www.tensorflow.org/tutorials/keras/overfit_and_un ...

  4. C#自带的Version判断版本号的大小

    Version version1 = new Version("1.0.0.25"); Version version2 = new Version("1.0.0.24& ...

  5. svn服务器端—管理员分配权限

    1.SVN服务器搭建和使用 下载地址:http://subversion.apache.org/packages.html 滚动到浏览器底部,下载并安装:VisualSVN服务器端和tortoiseS ...

  6. bootstrap-table:操作栏点击编辑按钮弹出模态框修改数据

    核心代码: columns: [ { checkbox:true //第一列显示复选框 }, ... { field: 'fail_num', title: '失败数' }, { field: 'op ...

  7. Duration和Period的区别--通俗易懂

    在jdk1.8以后,对表示日期时间的类型进行了重新分类,这里出现了2个新的类,Duraction 和Period Duraction表示:时间的区间,用来度量秒和纳秒之间的时间值 Period表示:一 ...

  8. Spring Security 官网文档学习

    文章目录 通过`maven`向普通的`WEB`项目中引入`spring security` 配置 `spring security` `configure(HttpSecurity)` 方法 自定义U ...

  9. Word 固定行间距公式图片显示不全、Word Eculid 字体导致行间距过大、Word 行间距过大

    1. 前言 1.有些文章行间距要求是固定值,比如,固定值15磅,但是这样会导致有些公式.图片显示不全.例如下图: 2.Euclid这个字体很容易导致行间距超大. 2. 解决方案 1.把固定值15磅改为 ...

  10. ~ubuntu1804安装禅道

    一.解压禅道安装包 二.启动禅道 # 开启Apache和Mysql服务 /opt/zbox/zbox start # 停止Apache和Mysql服务 /opt/zbox/zbox stop # 命令 ...