There is a technical term for what your first code is doing: returning a dangling pointer
When you create variables in a function, they are allocated on a small area of memory called the stack, which acts like a "stack of coins":
You call a function, and the address you cam from is "pushed" on the top of the stack.
The function then allocates memory and pushes that to the top of the stack.
The function runs, and used the variables
When you return, the function "pops" all the variables it stacked off again, then "pops" the return address off and goes back where it came from with that.
When you return a pointer to a local variable from teh function, the pointer is to memory that has been freed, and that will be used by the next function call. So the call to printf will corrupt memory that you pointed to and things ... start to go wrong in unpredictable ways ...
When you allocate memory using
, it doesn't come from the stack - it comes from a much, much larger area of memory called the heap and that isn't released until you explicitly call
and pass the pointer to it.
If you don't call
then your code probably won't crash for a long time - but it will start to "leak memory" because the heap while large is not infinite!
The size of the stack and the usage above also explains why you will get "out of memory" or "stack overflow" errors if you deliberately or accidentally start using direct or indirect recursion without adequate checks in place!