Ok, I'll bite. What difference does it make?
Say you have a queue of pointers that some thread is chewing on, you can't stick a pointer to a stack variable into that queue and then exit the scope of that stack variable, but you could put a longer lived heap pointer into that queue and exit the scope of the pointer, essentially passing ownership of the pointer to whatever's chewing on the other end of the queue.
Dereferencing said pointers isn't any different, no matter how the pointee was allocated:
void myfun(void *foo) {
// do things with foo.
// how it was allocated is all the same to me
}
As far as C is concerned, stack and heap do not exist. The validity of reference to an object is defined in terms of lifetime, which stems from its storage duration (static/automatic/allocated).And these are concepts that just define the semantics of the language. For example, an object with automatic storage duration might never hit stack or heap or any other part of RAM; it could live in registers, or be optimized out altogether. It could be in the bss segment. The semantics also do not forbid the implementation from using mmap() or malloc() (or similar) for objects with automatic storage duration.
Using stack for automatic variables and heap for allocated variables is just one implementation technique, which should not give rise to any observable differences in the meaning of a legal program (i.e. one that doesn't go into undefined behavior) as interpreted by the abstract machine, which the standard defines.