Reputation: 143
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
Reputation: 3465
Quoting sequencing rules (emphasis mine)
- 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
- 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
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:
func
are evaluated in no particular order:
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.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.)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
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
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