关于main函数以及其他函数返回值
若main函数没有return函数会默认返回 0 (对于main函数,编译器会自动返回0;)
若其他函数没有return 会返回上一次返回的内容(对于其他函数,返回值取决于上一次eax寄存器移入的值。)
** **
知乎链接:c语言中int main()主函数的结尾为何有时有return 0有时没有? - 刘彬的回答 - 知乎
** **
备份:
{
作者:刘彬 链接:https://www.zhihu.com/question/51597277/answer/126739598 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
以上所有答案都不完整,甚至还有错误的答案, 其实这种问题,试试不就知道了吗。 写一个test.c:
#include <stdio.h>
int test1(void)
{
return 0;
}
int test2(void)
{
return -1;
}
int test3(void)
{
}
int main(void)
{
int a1,a2,a3;
a1=test1();
a2=test2();
a3=test3();
printf("%d %d %d",a1,a2,a3);
}
编译一下,不要优化
gcc -S -O0 test.c
得到一个test.s :
.file "test.c" .text .globl test1 .def test1; .scl 2; .type 32; .endef .seh_proc test1 test1: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 .seh_endprologue movl $0, %eax popq %rbp ret .seh_endproc .globl test2 .def test2; .scl 2; .type 32; .endef .seh_proc test2 test2: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 .seh_endprologue movl $-1, %eax popq %rbp ret .seh_endproc .globl test3 .def test3; .scl 2; .type 32; .endef .seh_proc test3 test3: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 .seh_endprologue nop popq %rbp ret .seh_endproc .def __main; .scl 2; .type 32; .endef .section .rdata,"dr" .LC0: .ascii "%d %d %d\0" .text .globl main .def main; .scl 2; .type 32; .endef .seh_proc main main: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 subq $48, %rsp .seh_stackalloc 48 .seh_endprologue call __main call test1 movl %eax, -4(%rbp) call test2 movl %eax, -8(%rbp) call test3 movl %eax, -12(%rbp) movl -12(%rbp), %ecx movl -8(%rbp), %edx movl -4(%rbp), %eax movl %ecx, %r9d movl %edx, %r8d movl %eax, %edx leaq .LC0(%rip), %rcx call printf movl $0, %eax addq $48, %rsp popq %rbp ret .seh_endproc .ident "GCC: (tdm64-1) 5.1.0" .def printf; .scl 2; .type 32; .endef
其中rbp寄存器是帧指针,eax寄存器用于返回值。 其中 test1 ,test2,帧指针出栈前会把返回值放入eax中,例如 test1的情况
movl $0, %eax
eax寄存器是要求调用者保存的寄存器,也就是说函数返回时,eax是不会出栈的。 注意到test3中没有这条指令,也就是说test3函数没有对eax寄存器的操作,那么返回值取决于上一次对eax寄存器的操作。 有意思的是main函数,虽然也没有return语句,但在返回前有一条指令把eax设为0了,也就是编译器自动设置返回0。
运行一下试试
gcc -o test -O0 test.c
运行结果为 0 -1 -1,大家可以自己试一下。 也就是说test3返回了-1,实际上就是上一次test返回时eax寄存器移入的值。 结论: 对于main函数,编译器会自动返回0; 对于其他函数,返回值取决于上一次eax寄存器移入的值。
对了,以上结论只是在x86体系中,gcc编译器,而且优化为O0的结果。另外@SuperSodaSea 提到标准中普通函数中这种做法是未定义行为。所以实际项目中普通函数的return 语句一定要写。
** **
}
** **