C语言二级指针底层实现

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
posted @ 2019-09-15 13:29  可酷可乐  阅读(511)  评论(2编辑  收藏  举报