关于退货声明的混淆

时间:2014-02-16 09:10:55

标签: c return

int demo()
{
   static int i = 1;
   return i++;
}

int main()
{
    printf("%d %d %d\n", demo(), demo(), demo());
    return 0;
}  

输出: -

3 2 1

在第一次demo通话期间,会返回1

我听说当执行return语句时,控件会传递给calling函数,而不会在called函数中进一步执行代码。

所以我的问题是,在我的代码中,在第一次调用时返回1时,为什么它的值会递增?

换句话说,我想知道在返回1之后,为什么要执行++

4 个答案:

答案 0 :(得分:1)

int demo()
{
   static int i = 1;
   return i++;
}

int main()
{
    printf("%d %d %d\n", demo1(), demo2(), demo3());
    return 0;
}  

demo_i()的执行顺序取决于语言。

现在,使用static关键字。 Static variables stack会在整个计划期间持续function,即使在returns结束且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 . 之后也是如此。

{{1}}

希望这有帮助!

答案 1 :(得分:0)

这里要记住三点:

  1. static个函数在第一次创建时会持续整个程序的持续时间

  2. 返回的变量也有 postfix ++运算符,这意味着:“使用该值(即返回它)并将其递增”AFTERWARDS“:不返回递增的值。

  3. 这就是为什么这个变量对所发生的事情有“记忆”并且会增加。

    - >你为什么看到“3 2 1”而不是“1 2 3”?

    评估参数的顺序不是'先验',而是由编译器决定,参见https://stackoverflow.com/a/12960263/1938163


    如果您真的想知道如何首先返回值然后递增,请查看生成的asm代码:

    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"
    

    64位ABI使用寄存器(RDI,RSI,RDX,RCX,R8和R9)代替堆栈进行参数传递。

答案 2 :(得分:0)

您的函数返回i的旧值并递增它。由于您使用了static关键字,因此i的值已存储并可供下次调用(调用后不会消失)。

  

我听说当执行return语句时,控制传递给调用函数,而不会在被调用函数中进一步执行代码。

你听到了。但这并不意味着return语句返回的语句不会被执行。查看示例:

return a + b;  

现在执行此语句然后首先评估a+b,然后将其值返回给调用者。

以类似的方式
return i++;

执行,然后执行i++。它返回先前的i值并将其递增1

答案 3 :(得分:0)

  

[...]我想知道在返回1后,为什么要执行++?

后缀运算符由C标准定义为:

  

6.5.2.4后缀增量和减量运算符

     

[...]

     

2 postfix ++运算符的结果是操作数的值。结果之后   获得后,操作数的值递增。 (即,适当的值1   类型被添加到它。)

所以在执行return之前i是递增的,但由于后缀操作的结果是“原始”值,return会返回此“原始”值。