函数返回值如何对我来说是清楚的,只是为了启动:
int f()
{
int a = 2;
return a;
}
Run Code Online (Sandbox Code Playgroud)
现在a获取堆栈中的内存并且它的生命周期在其中f()以便返回它将值复制到一个特殊寄存器的值,该寄存器由调用者知道被调用者为他放置了值.(由于返回值持有者特殊寄存器大小的大小是有限的,这就是为什么我们不能返回大对象因此如果我们想要返回对象函数的高级语言实际上将堆中对象的地址复制到该特殊寄存器)
当我想返回一个不是指针的struct变量时,让我们回到C的情况:
struct inventory
{
char name[20];
int number;
};
struct inventory function();
int main()
{
struct inventory items;
items=function();
printf("\nam in main\n");
printf("\n%s\t",items.name);
printf(" %d\t",items.number);
getch();
return 0;
}
struct inventory function()
{
struct inventory items;
printf(" enter the item name\n ");
scanf(" %s ",&items.name );
printf(" enter the number of items\n ");
scanf("%d",&items.number );
return items;
}
Run Code Online (Sandbox Code Playgroud)
代码来自:https://stackoverflow.com/a/22952975/962545
这是交易,
让我们从main, …
函数的返回值通常存储在堆栈或寄存器中.但对于大型结构,它必须在堆栈上.在这个代码的真实编译器中必须进行多少复制?还是优化了?
例如:
struct Data {
unsigned values[256];
};
Data createData()
{
Data data;
// initialize data values...
return data;
}
Run Code Online (Sandbox Code Playgroud)
(假设函数无法内联..)
c compiler-theory abi calling-convention compiler-optimization
(gdb) disas func
Dump of assembler code for function func:
0x00000000004004b8 <func+0>: push %rbp
0x00000000004004b9 <func+1>: mov %rsp,%rbp
0x00000000004004bc <func+4>: movl $0x64,0xfffffffffffffff0(%rbp)
0x00000000004004c3 <func+11>: movb $0x61,0xfffffffffffffff4(%rbp)
0x00000000004004c7 <func+15>: mov 0xfffffffffffffff0(%rbp),%rax
0x00000000004004cb <func+19>: leaveq
0x00000000004004cc <func+20>: retq
End of assembler dump.
t_test func()
{
t_test t;
t.i = 100;
t.c = 'a';
return t;
}
Run Code Online (Sandbox Code Playgroud)
所以它似乎正在返回局部变量t,但这种工作是否有保证可以工作,是不是应该在返回时不引用任何局部变量?
(这个问题特定于我的机器的架构和调用约定,Windows x86_64)
我不记得我在哪里读过这个,或者我是否正确地回忆过它,但我听说过,当一个函数应该按值返回一些结构或对象时,它会填充它rax(如果对象可以适合在寄存器宽度为64位)或传递一个指针,指向结果对象将在哪里(我猜测在调用函数的堆栈帧中分配)rcx,在那里它将执行所有通常的初始化,然后a mov rax, rcx为返回行程.就是这样的
extern some_struct create_it(); // implemented in assembly
Run Code Online (Sandbox Code Playgroud)
真的会有一个秘密的参数
extern some_struct create_it(some_struct* secret_param_pointing_to_where_i_will_be);
Run Code Online (Sandbox Code Playgroud)
我的记忆是正确的,还是我错了?如何通过函数的值返回大对象(即宽度超过寄存器宽度)?