C is not garbage collected. So the garbage collected is never called because there is no garbage collector (unless you're using a lib which provides one - in which case it depends on the lib of course).
The reason that your code (which of course invokes undefined behavior, so might technically behave any way it wants) behaves the way it does is that i contains an address on the stack. The first time you dereference i that address has not yet been re-used because you haven't invoked any other function yet. So it still stores the previous value of k, i.e. 12. The second time you dereference i, printf has been called and presumably stored something on that location on the stack. So it now holds whichever value has been stored there by printf. And that's the value that gets printed.