To my understanding, each thread usually gets only one stack (while all threads in a process usually share a heap). I always thought that stack is used for storing the value of Program Counter(PC) when function call happens. But then I read somewhere that certain variable types such as integer or boolean are allocated onto the stack as well. Since values on stacks are managed in a strict FILO manner, how can these variables be retrieved at any time?
For example, after declaring int a, b, c;, I can do whatever I want to these variables in any order at any time within their scope. How is this done? Why isn’t value c on the top of the stack and therefore hiding values a, b?
The call stack is also used for local variables, and also for passing parameters into a function.
You are right in that ‘Value types’ are passed on the stack, whereas reference types are allocated on the heap, but when a reference type is used as a parameter, a pointer to this heap location will be still passed on the stack.
Although stacks are usually ‘perceived’ as LIFO buffers, there are also frame or base pointers associated with the call stack, which can be used to directly access memory above or below the current stack pointer. This is how functions can still have random access to parameters without changing the stack pointer.
This diagram from Wikipedia may help visualize this, although note that many would argue that the stack should grow ‘downwards’.
This blog post here explains Intel call stacks