Though the actual implementation is platform specific, this idea is the cause for potentially dangerous buffer overflows. For example,
-------------
| arr[0] | \
------------- \
| arr[1] | -> arr[3] is local to a function
------------- /
| arr[2] | /
-------------
| frame ptr |
-------------
| ret val |
-------------
| ret addr |
-------------
| args |
-------------
My question is, is there a reason why the local array, for lack of a better verb, flows down? Instead, if the array was to flow up, wouldn’t it significantly reduce the number of buffer overflow errors that overwrite the return address?
Granted, by using threads, one could overwrite the return address of a function that the current one has called. But lets ignore it for now.
The array on the stack works just like an array on the heap, i.e. its index increases as the memory address increases.
The stack grows downwards (towards lower addresses) instead of upwards, which is the reason for the array going in the opposite direction of the stack. There is some historic reason for that, probably from the time when the code, heap and stack resided in the same memory area, so the heap and the stack grew from each end of the memory.