return 语句的表达式结果存储在内存的哪一部分?
which part of the memory does the result of the expression of the return statements gets stored in?
情况是
int func(void){
int A = 10;
int B = 20;
return A+B
}
被主函数调用
int main(void){
int retVal = func();
return 0;
}
在函数func()
中,两个局部变量将被存储到func()
作用域的堆栈中,但是A+B的结果存储在哪里?
通过引用调用,这种方法的可靠性如何?
下面的函数体有什么区别
int func(void){
int A = 20;
return A;
}
和
int* func(void){
int A = 20;
return &A;
}
为什么返回值不会抛出段错误,但返回地址会抛出?
where does the result of A+B stored?
这强烈地取决于特定的体系结构和特定的调用约定——每个体系结构都是不同的。让我们检查最常见的一个 - Linux 上的 x86-64(参见 https://en.wikipedia.org/wiki/X86-64 , https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl , Where is the x86-64 System V ABI documented? , https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture)。
你提供的函数被gcc编译为godbolt link:
func:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 10
mov DWORD PTR [rbp-8], 20
mov edx, DWORD PTR [rbp-4]
mov eax, DWORD PTR [rbp-8]
add eax, edx
pop rbp
ret
在 x86-64 上,return 值存储在 eax
寄存器中。 add eax, edx
将加法结果放入 eax
寄存器。设置eax
后,函数比returns,main
如果想得到return的值,可以读取eax
寄存器的内容。
in the function func() two local variables will be stored onto the stack for the scope of func() but where does the result of A+B stored?
取决于目标体系结构的特定调用约定,通常在寄存器中(例如 x86 上的 eax
)。
what is the difference between following function bodies
int func(void){
int A = 20;
return A;
}
and
int* func(void){
int A = 20;
return &A;
}
在第一种情况下,您将返回 表达式 A
的结果,它只是整数值 20
; IOW,值 20
被写入某个寄存器或其他内存位置,由调用函数读取。
在第二种情况下,您将返回表达式 &A
的结果,即 [=18= 中变量 A
的 地址 ].这样做的问题是,一旦 func
退出,A
将不复存在,并且该内存位置可用于其他用途;指针值不再 有效 ,取消引用无效指针的行为未定义。
鉴于您用“C”关键字标记了它,值得一提的是 C 早期的意图是 return 值,作为整数或指针,应该适合处理器寄存器,因此没有分配内存来存储该值。
调用函数可能需要声明一个变量来存储结果,它负责分配。在函数 return 上,调用者立即将商定的处理器寄存器值存储到它保留的内存中。当然,如果该值立即用于某些其他计算,则可能没有必要。
当return指向一个指针时,指针指向的是程序员的问题:你。正如您所发现的,如果您尝试访问一个值,您只在被调用函数中声明为局部变量并使用指针 returned,则局部变量 space - 函数调用堆栈 - 非常重要重复使用,你的价值将很快被废弃。
当然,您可以 return 现代 C 和 C++ 中的浮点值和结构,这通常需要不同的处理方式。通常调用函数必须为被调用函数保留space来存储这些更大的对象。
请注意,编译器通常能够内联和优化代码以使用可用的寄存器,而不是重复使用约定的寄存器,有时甚至用一组寄存器替换小结构。
godbolt 等工具可以让您轻松查看编译器对您的代码做了什么。
情况是
int func(void){
int A = 10;
int B = 20;
return A+B
}
被主函数调用
int main(void){
int retVal = func();
return 0;
}
在函数func()
中,两个局部变量将被存储到func()
作用域的堆栈中,但是A+B的结果存储在哪里?
通过引用调用,这种方法的可靠性如何?
下面的函数体有什么区别
int func(void){
int A = 20;
return A;
}
和
int* func(void){
int A = 20;
return &A;
}
为什么返回值不会抛出段错误,但返回地址会抛出?
where does the result of A+B stored?
这强烈地取决于特定的体系结构和特定的调用约定——每个体系结构都是不同的。让我们检查最常见的一个 - Linux 上的 x86-64(参见 https://en.wikipedia.org/wiki/X86-64 , https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl , Where is the x86-64 System V ABI documented? , https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture)。
你提供的函数被gcc编译为godbolt link:
func:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 10
mov DWORD PTR [rbp-8], 20
mov edx, DWORD PTR [rbp-4]
mov eax, DWORD PTR [rbp-8]
add eax, edx
pop rbp
ret
在 x86-64 上,return 值存储在 eax
寄存器中。 add eax, edx
将加法结果放入 eax
寄存器。设置eax
后,函数比returns,main
如果想得到return的值,可以读取eax
寄存器的内容。
in the function func() two local variables will be stored onto the stack for the scope of func() but where does the result of A+B stored?
取决于目标体系结构的特定调用约定,通常在寄存器中(例如 x86 上的 eax
)。
what is the difference between following function bodies
int func(void){ int A = 20; return A; }
and
int* func(void){ int A = 20; return &A; }
在第一种情况下,您将返回 表达式 A
的结果,它只是整数值 20
; IOW,值 20
被写入某个寄存器或其他内存位置,由调用函数读取。
在第二种情况下,您将返回表达式 &A
的结果,即 [=18= 中变量 A
的 地址 ].这样做的问题是,一旦 func
退出,A
将不复存在,并且该内存位置可用于其他用途;指针值不再 有效 ,取消引用无效指针的行为未定义。
鉴于您用“C”关键字标记了它,值得一提的是 C 早期的意图是 return 值,作为整数或指针,应该适合处理器寄存器,因此没有分配内存来存储该值。
调用函数可能需要声明一个变量来存储结果,它负责分配。在函数 return 上,调用者立即将商定的处理器寄存器值存储到它保留的内存中。当然,如果该值立即用于某些其他计算,则可能没有必要。
当return指向一个指针时,指针指向的是程序员的问题:你。正如您所发现的,如果您尝试访问一个值,您只在被调用函数中声明为局部变量并使用指针 returned,则局部变量 space - 函数调用堆栈 - 非常重要重复使用,你的价值将很快被废弃。
当然,您可以 return 现代 C 和 C++ 中的浮点值和结构,这通常需要不同的处理方式。通常调用函数必须为被调用函数保留space来存储这些更大的对象。
请注意,编译器通常能够内联和优化代码以使用可用的寄存器,而不是重复使用约定的寄存器,有时甚至用一组寄存器替换小结构。
godbolt 等工具可以让您轻松查看编译器对您的代码做了什么。