doraemon1
doraemon1

Reputation: 143

about postfix operator and sequence point

void func(int a){
printf("%d",a);
}

int main(){
  int a= 0;
  printf("%d", a);
  func(a++);
}

This is my code BUT I can't understand why the result is 0 I think the result has to be 1

Because :

The side effect of updating the stored value of the operand shall occur between the previous and the next sequence point.

"a has to be increased before next sequence point"

All side effects of argument expression evaluations are sequenced before the function is entered

"There's sequence point before function is called"

So Isn't the variable a to be increased before func is called?

Can you tell me what am I understanding wrong?

THANK YOU

Upvotes: 0

Views: 108

Answers (4)

Zoso
Zoso

Reputation: 3465

Quoting sequencing rules (emphasis mine)

  1. When calling a function (whether or not the function is inline and whether or not function call syntax was used), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body.

So, there's a sequence point after the evaluation of the function arguments. Now, this read with

  1. Between the previous and next sequence point a scalar object must have its stored value modified at most once by the evaluation of an expression, otherwise the behavior is undefined.

will explain what is happening. The evaluation of the argument will happen and then there's a sequence point. The previous sequence point was the previous statement. So, evaluation of a++ will yield 0 since it's the postfix operator. This is what is passed to the function and hence the value 0.

Here's confirming what's happening via assembly for the code

void foo(int a) {}

int main()
{
    int a = 0;
    foo(a++);
    return 0;
}

which yields the assembly:

foo:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        nop
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], 0
        mov     eax, DWORD PTR [rbp-4]
        lea     edx, [rax+1]
        mov     DWORD PTR [rbp-4], edx
        mov     edi, eax
        call    foo

0 is moved at the memory location with the value of rbp-4. Then that value is moved to the register eax. mov edi, eax moves this value to the edi register which is actually used by the foo function, called via call foo.

lea     edx, [rax+1]
mov     DWORD PTR [rbp-4], edx

These 2 instructions increment and store the value of a.

Upvotes: 0

Ian Abbott
Ian Abbott

Reputation: 17503

Consider the following program:

#include <stdio.h>

int a; /* global */

void func(int arg) {
    printf("func: arg=%d, (global) a=%d\n", arg, a);
}

int main(void){
    a = 0;
    printf("main: (global) a=%d\n", a);
    func(a++);
    printf("main: (global) a=%d\n", a);
}

That program uses a global variable a. In main, the expression statement func(a++); is evaluated in the following order:

  1. The arguments of func are evaluated in no particular order:
    1. For func's arg parameter, the argument expression a++ is evaluated yielding the old value of a (the value 0) with the side effect of a being incremented before the next sequence point.
  2. Any remaining side effects of argument evaluation are completed (so a will be incremented to 1). (This is the sequence point after the evaluation of the function designator and function arguments but before the actual call.)
  3. func is actually called.

(I have omitted some details, such as evaluation of the function designator func.)

The result of the above is that the old value of a (value 0) is passed to the arg parameter of func, but a will have been incremented (to value 1) when the body of function func is executed.

The above behavior can be seen in the program's output:

main: (global) a=0
func: arg=0, (global) a=1
main: (global) a=1

Upvotes: 0

Eric Postpischil
Eric Postpischil

Reputation: 223673

func(a++) does not pass a to the function. It passes the value of the expression a++. The value of that expression is defined to be the value of a before the increment occurs.

It is entirely irrelevant when the increment occurs. The value of a++ is the value of a prior to the increment.

Upvotes: 2

dbush
dbush

Reputation: 224437

The postfix ++ operator evaluates to the current value of its operand, with the increment being a side effect.

So since a is 0 to start, that's the value that is passed to the function.

Upvotes: 1

Related Questions