You are returning the address of the local variable c
. This is undefined behavior. That is, your program is erroneous and this means that it has no obligation to show a predictable or sane behavior. Changing the position of the two printf
gives you another erroneous program, which (again) is not required to behave correctly or coherently with the previous erroneous program.
EDIT (adding relevant citations from C99 draft standard N1256 - emphasis mine)
6.5.3.2 Address and indirection operators
[...]
Semantics
The unary * operator denotes indirection. If the operand points to a function, the result is
a function designator; if it points to an object, the result is an lvalue designating the
object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an
invalid value has been assigned to the pointer, the behavior of the unary * operator is
undefined.87)
(footnote #87)
Thus, &*E
is equivalent to E
(even if E
is a null pointer), and &(E1[E2])
to ((E1)+(E2))
. It is always true that if E is a function designator or an lvalue that is a valid operand of the unary &
operator, *&E
is a function designator or an lvalue equal to E
. If *P
is an lvalue and T
is the name of an object pointer type, *(T)P
is an lvalue that has a type compatible with that to which T
points.
Among the invalid values for dereferencing a pointer by the unary *
operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.
The relevant sentence is the last one (emphasis mine): the c
local variable has already ended its lifetime by the time when its address, which was returned by the addition
function, is dereferenced in main
.