C 语言指针 引用学习
举个实例
1 #include<stdio.h> 2 int test_num; 3 void func(int *p) 4 { 5 p = &test_num; 6 } 7 int main(void) 8 { 9 int *p; 10 func(p); 11 *p = 1000; 12 return 0; 13 }
运行出core
反汇编:
gcc -S t3.c -o t3.s
.file "t3.c" .comm test_num,4,4 .text .globl func .type func, @function func: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movq %rdi, -24(%rbp) movq $test_num, -8(%rbp) popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size func, .-func .globl main .type main, @function main: .LFB1: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movq -8(%rbp), %rax movq %rax, %rdi call func movq -8(%rbp), %rax movl $1000, (%rax) movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1: .size main, .-main .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4" .section .note.GNU-stack,"",@progbits
main函数在call func之前:
movq -8(%rbp), %rax
movl $1000, (%rax)
明显的错误,把ebp的下4字节的内容移动到当前esp所指向的内容,实际上做了一个*p的副本,为func函数使用;
调用func函数后:
movq $test_num, -8(%rbp)
于是,func函数操作的只是*p的副本,把副本里存放了test_num的首地址。
ret回main函数后,变量test_num赋值为1000,main函数里的*p,是不知道的,因为,只有它的副本知道。
更改源码:
1 #include<stdio.h> 2 int test_num; 3 void func(int **p) 4 { 5 *p = &test_num; 6 } 7 int main(void) 8 { 9 int *p; 10 func(&p); 11 *p = 1000; 12 return 0; 13 }
反汇编处理:
1 .file "t3.c" 2 .comm test_num,4,4 3 .text 4 .globl func 5 .type func, @function 6 func: 7 .LFB0: 8 .cfi_startproc 9 pushq %rbp 10 .cfi_def_cfa_offset 16 11 .cfi_offset 6, -16 12 movq %rsp, %rbp 13 .cfi_def_cfa_register 6 14 movq %rdi, -8(%rbp) 15 movq -8(%rbp), %rax 16 movq $test_num, (%rax) 17 popq %rbp 18 .cfi_def_cfa 7, 8 19 ret 20 .cfi_endproc 21 .LFE0: 22 .size func, .-func 23 .globl main 24 .type main, @function 25 main: 26 .LFB1: 27 .cfi_startproc 28 pushq %rbp 29 .cfi_def_cfa_offset 16 30 .cfi_offset 6, -16 31 movq %rsp, %rbp 32 .cfi_def_cfa_register 6 33 subq $16, %rsp 34 leaq -8(%rbp), %rax 35 movq %rax, %rdi 36 call func 37 movq -8(%rbp), %rax 38 movl $1000, (%rax) 39 movl $0, %eax 40 leave 41 .cfi_def_cfa 7, 8 42 ret 43 .cfi_endproc 44 .LFE1: 45 .size main, .-main 46 .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4" 47 .section .note.GNU-stack,"",@progbits
可以看到有发生变化
也就是说,作为副本供func函数使用的不是ebp下4个字节的内容,而是内容里所指向的地址(即mian函数*p的地址)。