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

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

output:-

3 2 1

During the first demo call, 1 is returned.

I have heard that when return statement is executed, then control passes to the calling function without any further execution of code in called function.

So my question is that in my code when 1 is returned in first call, Why its value is incremented?

In other words I want to know that after returning 1 , why ++ is executed?

alk
  • 69,737
  • 10
  • 105
  • 255
zee
  • 188
  • 2
  • 2
  • 9
  • 3
    postfix ++ returns the old *value*, *and* increments the *variable*. Don't confuse these two concepts. The increment is a side-effect of the operator. – Elazar Feb 16 '14 at 09:12
  • While compiling this program use `-Wall` option of gcc and it will show you warning that behaviour may be undefined! – Nullpointer Feb 16 '14 at 09:14
  • Pretty similar to [this question](http://stackoverflow.com/questions/21808791/struct-vrs-classes-padding-templates) asked a little while back. – devnull Feb 16 '14 at 09:14
  • @Elazar : but in my case, when value is returned, so how it is incremented as the control is now in the `main()` – zee Feb 16 '14 at 09:14
  • @zee, "after" does not mean "after the control has returned to `main()`. It's just "after calculating the value to be returned". You may think about it as sort of "`++i; return i-1;`" (ignoring overflow here). – Elazar Feb 16 '14 at 09:15
  • 1
    @JoachimPileborg It's implementation defined. – devnull Feb 16 '14 at 09:18
  • Anyway, the control is returned only after all the side effects of the statements have been computed. – Elazar Feb 16 '14 at 09:18
  • @Nullpointer gcc does not warn me with `-Wall -Wextra`. –  Feb 16 '14 at 09:20
  • @Elazar : but if the side effects are calculated first, then its incremented value will be returned – zee Feb 16 '14 at 09:21
  • @zee, no. again, it may be compiled into: `temp = i; i++; return temp;`. You are thinking too "literaly" about the flow, and you're doing it wrong. `i++` is a *single* expression, with both *value* and *sideeffect*. – Elazar Feb 16 '14 at 09:22
  • @Elazar : you mean to say that the old value is stored to somewhere else for returning – zee Feb 16 '14 at 09:23
  • @zee that would be an implementation detail, which may or may not help you think about how it works. But yes. Assuming `i-1` gives you the correct old value, you won't need it. – Elazar Feb 16 '14 at 09:24
  • @zee Take a look at my answer http://stackoverflow.com/a/21809324/1938163 if you want a low-level step-by-step explanation with clang – Marco A. Feb 16 '14 at 09:46

4 Answers4

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

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

The order of execution of demo_i() is language dependent .

Now, comes use of static keyword . Static variables persist on the stack through the entire duration of the program , even after function ends and returns the value .

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 .  

Hope this helps !

Aseem Goyal
  • 2,683
  • 3
  • 31
  • 48
0

Three points to keep in mind here:

  1. static variables into functions persist through the entire duration of the program as soon as they're created for the first time

  2. That variable returned also has the postfix ++ operator which means: "use the value (i.e. return it) and increment it AFTERWARDS": the incremented value is not returned.

That's why that variable has "memory" of what happened and gets incremented.

-> Why you're seeing "3 2 1" instead of "1 2 3"?

The order in which the parameters are evaluated is not known 'a priori' and it's up to the compiler decide it, see https://stackoverflow.com/a/12960263/1938163


If you really want to know how is it possible that the value gets first returned and then incremented, take a look at the generated asm code:

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"

The 64-bit ABI uses registers (RDI, RSI, RDX, RCX, R8 and R9) instead of the stack for argument passing.

Community
  • 1
  • 1
Marco A.
  • 43,032
  • 26
  • 132
  • 246
  • please tell me what `eax` means? – zee Feb 16 '14 at 09:48
  • eax is a register, a memory location small enough to contain a value or an address. They're not variables and when you set one, it persists until you change it again, so in the above it is used to move the static variable value around. – Marco A. Feb 16 '14 at 09:53
0

Your function returns old value of i and increments it . Since you used static keyword the value of i is stored and available for next call (it is not vanished after the call).

I have heard that when return statement is executed, then control passes to the calling function without any further execution of code in called function.

You heard right. But it doesn't mean that the statement which is returned by return statement does not executed. See an example:

return a + b;  

Now this statement executed then a+b get evaluated first and then its value is returned to the caller. In a similar way when

return i++;

get executed then i++ is executed. It returns the previous value of i and increment it by 1.

haccks
  • 104,019
  • 25
  • 176
  • 264
0

[...] I want to know that after returning 1, why ++ is executed?

The postfix operator is defined by the C Standard to work like this:

6.5.2.4 Postfix increment and decrement operators

[...]

2 The result of the postfix ++ operator is the value of the operand. After the result is obtained, the value of the operand is incremented. (That is, the value 1 of the appropriate type is added to it.)

So before the return is executed i is increment, but as the result of the postfix operation is the "original" value, return returns this "original" value.

alk
  • 69,737
  • 10
  • 105
  • 255