4

I'm preparing for a job interview.

My c program is :

void foo(void)
{
    int a;
    printf("%d\n",a);
}

void bar(void)
{
    int a=42;
}

void main(void)
{
    bar();
    foo();
}

I'm getting the output as : 42

But how? I thought it would be some garbage value .

How the concept of execution stack or activation frame is applied in this?

Please explain

Thanks

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
HighBoots
  • 293
  • 1
  • 5
  • 5
    `42` is a perfectly sensible garbage value – Leeor Jan 28 '14 at 14:14
  • 1
    The votes to close as caused by “a problem that can no longer be reproduced or a simple typographical error” are off the mark. This question is neither. It can be reproduced in most C implementations by turning off optimization, and it is clearly not a typographical error. – Eric Postpischil Jan 28 '14 at 14:22
  • I am not the downvoter, but I perfectly understand why somebody wouldn't like your post: (1) the question title contains not much information, it talks about your personal problem, not about the technical question that you encounter (2) any good book or other resource should tell you that you should not print variables that are not initialized with a value (3) with sufficient warning levels, any decent compiler nowadays should just cry. – Jens Gustedt Jan 28 '14 at 14:23
  • 1
    @JensGustedt: (2) is irrelevant. The OP does not ask whether this is good practice or not or why. They ask a different question, why is this behavior observed when it is not within the behavior specified by the C standard. As a matter of fact, reasons for that do exist, and the reasons lie within the realm of computer programming. – Eric Postpischil Jan 28 '14 at 14:25
  • possible duplicate of [What does printf print for an unitialized variable?](http://stackoverflow.com/questions/5972978/what-does-printf-print-for-an-unitialized-variable) – Jens Gustedt Jan 28 '14 at 14:25
  • @EricPostpischil, you are right that these are not the good reasons, but the fact that we have seen that a lot of times. – Jens Gustedt Jan 28 '14 at 14:26
  • This is not quite a duplicate of http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794 but many of the ideas expressed in that answer are germane. Basically: you are relying on undefined behaviour. Anything can happen. **Something does happen**. "Something" is a subset of "anything". – Eric Lippert Jan 28 '14 at 19:16

3 Answers3

5

a is not initialized in function foo. Printing an uninitialized variable invokes undefined behavior.
In this case you may get anything, either expected or unexpected result. On my compiler the output is

 4203214  

The result may vary compiler to compiler, even different versions of same compiler could give you different results.
But one of the possible reason that you are getting 42 is because auto variables are often allocated on an execution stack. After the call of bar, 42 is placed on execution stack. This value remains in stack undisturbed. When foo is called, it might read that stack space for a and prints 42.
Try to optimize your code (compile with -o), you may get some different value for a.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • 1
    This answer is incorrect because “undefined behavior” is never a **cause** of any behavior; it is a **lack of a cause**. There **do exist** reasons why the behavior the OP observed occurred. Those reasons lie in how function calls and automatic variables are typically implemented. – Eric Postpischil Jan 28 '14 at 14:27
  • @EricPostpischil; The why I am getting different result? – haccks Jan 28 '14 at 14:33
  • @haccks: You are getting a different result because your C implementation behaves differently than the OP’s C implementation. But that difference is not **caused** by the fact that the C standard does not define the behavior. It is caused by decisions made by the implementors of the two C implementations. The fact that the OP observes output of “42” is undoubtedly caused by the fact that 42 is placed on the stack by `bar`, remains there undisturbed, and is found there when `foo` uses it. The C standard did not cause this. The use of a stack did. – Eric Postpischil Jan 28 '14 at 14:47
  • @EricPostpischil; But `a` is uninitialized. Doesn't that invokes UB? – haccks Jan 28 '14 at 14:54
  • 1
    @haccks: The phrase “invokes UB” is misguided. Let’s say you are a parent, and your teenage child goes out for the afternoon, and you do not tell them where to go. Your child goes to see a movie. That is undefined behavior: You did not specify they had to go to a movie. Did you cause them to go to a movie? Did you invoke their undefined behavior? If somebody asked why your child went to a movie, would you say they went to a movie because you did not specify where they had to go? It just does not make any sense. You did not invoke anything. It happened for other reasons. – Eric Postpischil Jan 28 '14 at 15:14
3

The call to bar() puts the value 42 on the stack. It is still there when foo() is called.

The stack frames of bar() and foo() are likely identical, or a least similar enough, so that the a in foo() keeps the value 42.

Of course, this is not guaranteed, and is Undefined Behavior. But rather than simply dismissing such questions, as is often done, for debugging code one often needs some understanding.

If you increase the optimizing level (at least in gcc), the behaviour you see would change.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
1

When you call bar() from main(), it sets a = 42 which lives on the stack one int down from where main() executes. When you call foo() from main() it prints the value of a which in this scope is also on the stack one int down from where main() executes.

By calling bar() first, you have set data on the stack, and since foo() and bar() have the same call frame, bar()'s a and foo()'s a end up in the same memory address.

As other answers have noted, though, this is undefined behavior. In this case, the value persists on the stack and ends up in the same location.

rjp
  • 1,760
  • 13
  • 15