… it holds a garbage value.
When anybody says an object has a garbage value, they are being imprecise with language.
There is no value that is a garbage value. For 32-bit two’s complement integers, there are the values −2,147,483,648 to +2,147,483,647. Each of them is a valid value. None of them is a garbage value.
What it actually means to say something has a garbage value, if the speaker understands C semantics, is that the value of the object is uncontrolled. It has not been set to any specific value, and therefore whatever value you get from using it is a happenstance of circumstances. It may be some value that was in the memory of the object before it was reserved to be the memory for that object.
However, it might be other things. When an object is uninitialized, the C standard not only has no requirement that the memory of the object have any particular value, it has no requirement that the object behave as if it had any fixed value at all. This frees the compiler for purposes that are useful for optimization in other situations. But it means that, if you have int x; printf("%d\n", x); int y = x+3; printf("%d\n", y);
, the compiler does not have to load x
from memory each time it is used. Because x
is uninitialized, the compiler is not required to do any work to load it from memory. For the printf("%d\n", x);
, the compiler might let x
be whatever value is in the register that would be used to pass the second argument to printf
. For the int y = x+3;
, the compiler might let x
be whatever is in some other register that it would use to hold the value of x
if x
were defined. This could be a different register. So printf("%d\n", x);
might print “47” while int y = x+3; printf("%d\n", y);
prints “−372”, not “50”.
Sometimes an uninitialized object might behave as if it started with the value zero. This is not uncommon in short programs such as the one in the question, where nothing has used the stack much yet, so the part of it reserved for j
is still in the initial state the program loader put it in, filled with zeros. But that is happenstance. When you change the program, the compiler might use a different part of the stack for j
, and that part might not have zeros in it, because it was used by some of the initial program start-up code that runs before main
starts.