Explain the output
#include<stdio.h>
int * fun(int a1,int b)
{
int a[2];
a[0]=a1;
a[1]=b;
return a;
}
int main()
{
int *r=fun(3,5);
printf("%d\n",*r);
printf("%d\n",*r);
}
Output after running the code:
3
-1073855580
I understand that a[开发者_StackOverflow社区2] is local to fun() but why value is getting changed of same pointer?
The variable a is indeed local to fun. When you return from that function, the stack is popped. The memory itself remains unchanged (for the moment). When you dereference r the first time, the memory is what you'd expect it to be. And since the dereference happens before the call to printf, nothing bad happens. When printf executes, it modifies the stack and the value is wiped out. The second time through you're seeing whatever value happened to be put there by printf the first time through.
The order of events for a "normal" calling convention (I know, I know -- no such thing):
- Dereference
r
(the first time through, this is what it should be) - Push value onto stack (notice this is making a copy of the value) (may wipe out a)
- Push other parameters on to stack (order is usually right to left, IIRC) (may wipe out a)
- Allocate room for return value on stack (may wipe out a)
- Call printf
- Push local printf variables onto stack (may wipe out a)
- Do your thang
- Return from function
If you change int a[2];
to static int a[2];
this will alleviate the problem.
Because r
points to a location on the stack that is likely to be overwritten by a function call.
In this case, it's the first call to printf
itself which is changing that location.
In detail, the return from fun
has that particular location being preserved simply because nothing has overwritten it yet.
The *r
is then evaluated (as 3) and passed to printf
to be printed. The actual call to printf
changes the contents of that location (since it uses the memory for its own stack frame), but the value has already been extracted at that point so it's safe.
On the subsequent call, *r
has the different value, changed by the first call. That's why it's different in this case.
Of course, this is just the likely explanation. In reality, anything could be happening since what you've coded up there is undefined behaviour. Once you do that, all bets are off.
As you've mentioned, a[2]
is local to fun()
; meaning it is created on the stack right before the code within fun()
starts executing. When fun
exits the stack is popped, meaning it is unwound so that the stack pointer is pointing to where it was before fun
started executing.
The compiler is now free to stick whatever it wants into those locations that were unwound. So, it is possible that the first location of a
was skipped for a variety of reasons. Maybe it now represents an uninitialized variable. Maybe it was for memory alignment of another variable. Simple answer is, by returning a pointer to a local variable from a function, and then de-referencing that pointer, you're invoking undefined behavior and anything can happen, including demons flying out of your nose.
When you compile you code with the following command:
$ gcc -Wall yourProgram.c
It will yield a warning, which says.
In function ‘fun’:
warning: function returns address of local variable
When r
is dereferenced in first printf
statement, it's okay as the memory is preserved. However, the second printf
statement overwrites the stack and so we get an undesired result.
Because printf is using the stack location and changes it after printing the first value.
精彩评论