Since x is a local variable, I thought I would get an error when I try to return it.
A more general answer to this problem is: Wrong code in C code does not necessarily produce a compiler or runtime error.
If you're very lucky, you will get a compiler error or warning.
If you're lucky, you'll get a runtime crash when the wrong code runs (this often happens with null pointer errors). This is easy to track down with a debugger.
But if you're not lucky, wrong code can cause crashes later on (in seemingly unrelated code), or silently corrupt some data structures (making your program behave in weird ways without crashing), or even appear to work fine (until you add seemingly harmless code elsewhere, or use a different compiler, or a different version of the same compiler, or just different compilation options).
Technically your code has undefined behavior at this line:
int* c = func1();
You're using the return value of func1
(writing it into c
). But that value is the address of a local variable in func1
, which no longer exists by the time func
has returned. That means the return value is an invalid pointer, and just using such a pointer leads to undefined behavior (you don't even have to dereference it).
printf("%d\n", *c); // output: 123123
Well, this line both uses the bad pointer (reading it from c
) and dereferences it. The program still appears to work fine.
printf("%d\n", *c); // output: 0
A seemingly harmless addition, but this line doesn't produce the expected output. Now it looks like silent data corruption.
Note that none of this is guaranteed. A different compiler or the same compiler using different optimization settings may well produce code that behaves differently. As far as the standard is concerned, a compiler has to produce code that matches the observable behavior of the C code. But C code whose behavior is undefined can cause anything to happen; there are no guarantees or restrictions on what the compiler can do with it.