C 关于返回语句的混淆
输出:-C 关于返回语句的混淆,c,return,C,Return,输出:- int demo() { static int i = 1; return i++; } int main() { printf("%d %d %d\n", demo(), demo(), demo()); return 0; } 在第一次demo调用期间,返回1 我听说,当执行return语句时,控制权会传递给调用的函数,而不会进一步执行调用的函数中的代码 所以我的问题是,在我的代码中,当第一次调用返回1时,为什么它的值会递增 换句话说,我想知道在
int demo()
{
static int i = 1;
return i++;
}
int main()
{
printf("%d %d %d\n", demo(), demo(), demo());
return 0;
}
在第一次demo
调用期间,返回1
我听说,当执行return
语句时,控制权会传递给调用的
函数,而不会进一步执行调用的
函数中的代码
所以我的问题是,在我的代码中,当第一次调用返回1
时,为什么它的值会递增
换句话说,我想知道在返回
1
之后,为什么执行++
这里要记住三点:
静态
函数中的变量在程序第一次创建时,会在整个过程中持续存在如果您真的想知道值是如何首先返回然后递增的,请查看生成的asm代码:
3 2 1
64位ABI使用寄存器(RDI、RSI、RDX、RCX、R8和R9)而不是堆栈来传递参数。函数返回
i的旧值并将其递增。由于您使用了static
关键字,因此i
的值将被存储并可用于下一次调用(调用后不会消失)
我听说,当执行return
语句时,控制传递给调用函数,而不需要在被调用函数中进一步执行代码
你没听错。但这并不意味着return
语句返回的语句不执行。请参见一个示例:
demo(): # @demo()
movl demo()::i, %eax # move i and put it into eax
movl %eax, %ecx # Move eax into ecx -> eax will be used/returned!
addl $1, %ecx # Increment ecx
movl %ecx, demo()::i # save ecx into i -> this is for the next round!
ret # returns!
main: # @main
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl $0, -4(%rbp)
callq demo() # Call demo()
movl %eax, -8(%rbp) # save eax in rbp-8 (contains 1, demo::i is 2 for the next round)
callq demo() # Call demo()
movl %eax, -12(%rbp) # save eax in rbp-12 (contains 2, demo::i is 3 for the next round)
callq demo() # Call demo()
leaq .L.str, %rdi # load str address
movl -8(%rbp), %esi # esi points to 1
movl -12(%rbp), %edx # edx points to 2
movl %eax, %ecx # move eax (3) into ecx (demo::i is 4 but doesn't get used)
movb $0, %al # needed by the ABI to call printf
callq printf # call printf() and display 3 2 1
movl $0, %ecx
movl %eax, -16(%rbp)
movl %ecx, %eax
addq $16, %rsp
popq %rbp
ret
demo()::i:
.L.str:
.asciz "%d %d %d\n"
现在执行此语句,然后首先计算a+b
get,然后将其值返回给调用者。以类似的方式
return a + b;
执行get executed,然后执行i++
。它返回以前的i
值,并将其递增1
return i++;
demo_i()
的执行顺序取决于语言
现在,使用static
关键字。
静态变量
在程序的整个过程中始终保持在堆栈上
,即使在函数
结束并且返回值之后也是如此
int demo()
{
static int i = 1;
return i++;
}
int main()
{
printf("%d %d %d\n", demo1(), demo2(), demo3());
return 0;
}
希望这有帮助
[…]我想知道,在返回1之后,为什么要执行++
后缀运算符由C标准定义为如下工作方式:
6.5.2.4后缀递增和递减运算符
[……]
2后缀++运算符的结果是操作数的值。结果出来之后
获取时,操作数的值将递增。(即,适当的
类型已添加到其中。)
因此,在执行return
之前,i
是递增的,但由于后缀操作的结果是“原始”值,return
返回此“原始”值。postfix++返回旧值,并递增变量。不要混淆这两个概念。增量是运算符的副作用。编译此程序时,请使用gcc的-Wall
选项,它将向您显示行为可能未定义的警告!与不久前的提问非常相似。@Elazar:但在我的例子中,当返回值时,它是如何递增的,因为控件现在位于它的实现定义的main()
@JoachimPileborg中。请告诉我eax
是什么意思?eax是一个寄存器,一个足够小的内存位置,可以包含一个值或一个地址。它们不是变量,当您设置一个变量时,它会一直存在,直到您再次更改它,因此在上面的示例中,它用于移动静态变量值。
Due to this , 1st time : i=1
return 1 , increment to 2 .
2nd time : i=2
return 2 , increment to 3 .
3rd time : i=3
return 3 , increment to 4 .