传值传引用背后的汇编代码分析

370 阅读1分钟

gcc编译

gcc main.c

反编译

objdump -d a.out

传值源代码

typedef struct{
    int arr[10000];
}node;

void func(node n){}

int main(){
    node n;
    func(n);
    return 0;
}

传值部分汇编代码

100000f81:      48 89 e5        movq    %rsp, %rbp
100000f84:      48 81 ec 90 38 01 00    subq    $80016, %rsp
100000f8b:      c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
100000f92:      48 89 e0        movq    %rsp, %rax
100000f95:      b9 88 13 00 00  movl    $5000, %ecx
100000f9a:      48 8d b5 b8 63 ff ff    leaq    -40008(%rbp), %rsi
100000fa1:      48 89 c7        movq    %rax, %rdi
100000fa4:      f3 48 a5        rep             movsq   (%rsi), %es:(%rdi)
100000fa7:      e8 c4 ff ff ff  callq   -60 <_func>

传引用源代码

typedef struct{
    int arr[10000];
}node;

void func(node *n){}

int main(){
    node n;
    func(&n);
    return 0;
}

传引用部分汇编代码

00000f80:      55      pushq   %rbp
100000f81:      48 89 e5        movq    %rsp, %rbp
100000f84:      48 81 ec 50 9c 00 00    subq    $40016, %rsp
100000f8b:      c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
100000f92:      48 8d bd b8 63 ff ff    leaq    -40008(%rbp), %rdi
100000f99:      e8 d2 ff ff ff  callq   -46 <_func>

分析

观察传值汇编代码可以发现,编译器分配了80016个字节,是node结点所需字节数(40000)的两倍(多出来的16字节是因为编译器通常会多分配一些字节,多出的字节是不固定的)。而传引用的情况下编译器只分配了40016个字节。显然,如果我们使用传值,编译器将把node赋值一遍传递给func函数。如果不是刻意为之,开发场景中需要进行这样的拷贝,传值是不可取的,它会浪费栈空间。