函数传参
基础类型
值传递
func f(a: Int) {
}
let a = 0
f(a: a)
#![allow(unused)] fn main() { fn f(a: i32) { } let a = 0; f(a); }
void f(int a) {
}
int a = 0;
f(a);
// arm64, AT&T
_main:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
// int a = 0;
mov w8, #0
str w8, [x29, #-4]
// f(a);
ldr x0, [x29, #-4]
bl _f
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret
_f:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret
地址/引用传递
func f(a: inout Int) {
a += 1
}
var a = 0
f(a: &a)
#![allow(unused)] fn main() { fn f(a: &mut i32) { *a += 1; } let mut a = 0; f(&mut a); println!("{}", a); }
void f(int *a) {
*a += 1;
}
int a = 0;
f(&a);
// arm64, AT&T
_main:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
// int a = 0;
mov w8, #0
str w8, [x29, #-4]
// f(&a);
sub x0, x29, #4
bl _f
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret
_f:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
// *a += 1;
ldr w8, [x0]
add w8, w8, #1
str w8, [x0]
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret
栈上复合类型
值传递
栈上复合类型值传递的时候把值完全复制了一份,以保证被调用的函数不会修改函数外部的值
struct S {
let a: Int
let b: Int
let c: Int
}
func f(s: S) {
}
let s = S(a: 0, b: 0, c: 0)
f(s: s)
#![allow(unused)] fn main() { #[derive(Clone)] struct S { a: i32, b: i32, c: i32, } fn f(s: S) { } let s = S { a: 0, b: 0, c: 0 }; f(s.clone()); }
struct S {
int a;
int b;
int c;
};
void f(struct S s) {
}
struct S s = {0, 0, 0};
f(s);
// arm64, AT&T
_main:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
// struct S s = {0, 0, 0};
mov w8, #0
str w8, [x29, #-4*3]
mov w8, #0
str w8, [x29, #-4*2]
mov w8, #0
str w8, [x29, #-4*1]
// f(s);
ldr w8, [x29, #-4*3]
str w8, [x29, #-4*6]
ldr w8, [x29, #-4*2]
str w8, [x29, #-4*5]
ldr w8, [x29, #-4*1]
str w8, [x29, #-4*4]
sub x0, x29, #4*6
bl _f
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret
_f:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret
地址/引用传递
栈上复合类型地址/引用传递的时候,被调用函数和外部共享同一份栈上内存,因此函数内部更改也会更改外部
struct S {
let a: Int
let b: Int
let c: Int
}
func f(s: inout S) {
s = S(a: 1, b: 1, c: 1)
}
var s = S(a: 0, b: 0, c: 0)
f(s: &s)
#![allow(unused)] fn main() { struct S { a: i32, b: i32, c: i32, } fn f(s: &mut S) { *s = S { a: 1, b: 1, c: 1 }; } let mut s = S { a: 0, b: 0, c: 0 }; f(&mut s); }
struct S {
int a;
int b;
int c;
};
void f(struct S *s) {
s->a = 1;
s->b = 1;
s->c = 1;
}
struct S s = {0, 0, 0};
f(&s);
// arm64, AT&T
_main:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
// struct S s = {0, 0, 0};
mov w8, #0
str w8, [x29, #-4*3]
mov w8, #0
str w8, [x29, #-4*2]
mov w8, #0
str w8, [x29, #-4*1]
// f(&s);
sub x0, x29, #4*3
bl _f
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret
_f:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
// s->a = 1;
mov w8, #1
str w8, [x0]
// s->b = 1;
mov w8, #1
str w8, [x0, #4]
// s->c = 1;
mov w8, #1
str w8, [x0, #4*2]
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret
堆上复合类型
堆上复合类型把保存在栈上的堆内存地址传给了被调用的函数,因此被调用函数可以根据堆内存地址找到堆内存以修改堆内存数据
地址/引用传递
class C {
var a: Int
init(a: Int) {
self.a = a
}
}
func f(c: C) {
c.a += 1
}
let c = C(a: 0)
f(c: c)
#![allow(unused)] fn main() { struct C { a: i32, } fn f(c: &mut Box<C>) { c.a += 1; } let mut c = Box::new(C { a: 0 }); f(&mut c); }
struct C {
int a;
};
void f(struct C *c) {
c->a += 1;
}
struct C *c = malloc(sizeof(struct C));
c->a = 0;
f(c);
// arm64, AT&T
_main:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
// struct C *c = malloc(sizeof(struct C));
mov x0, #4
bl _malloc
str x0, [x29, #-8]
// c->a = 0;
mov w8, #0
ldr x9, [x29, #-8]
str w8, [x9]
// f(c);
ldr x0, [x29, #-8]
bl _f
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret
_f:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
// c->a += 1;
ldr w8, [x0]
add w8, w8, #1
str w8, [x0]
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret