The Joy of Programming
Allocation of Local Variables in Stack
It is always fun to understand the low-level details of a program and to explore how compilers
work. In this column, we’ll see some details on how local variables are allocated in stack and
some interesting issues on how compilers handle it.
Every month, I get lots of mails and queries from LFY readers. This column seems to have become
popular, particularly among students. This month, we’ll cover an interesting question from
Saravanan swamy (GCT, Coimbatore). His question is: Why does the following program print 10?
int i = 10;
Note that the printf doesn’t obviously have i as matching argument for the format string “%d”.
So, the program is incorrect and you can reasonably expect the program to print some garbage
value. But note that it is equally possible that you might get 10 as output. Why? To understand
this, let us see how compiler might transform these statements to low-level executable code.
Local variables are allocated in the stack frame of a function. When the main method is invoked,
the storage space for i is also allocated in the stack frame. A compiler should generate code to
initialize that value i with 10. The machine code will have instructions to load the value 10 in a
register and store it in the location for i in the stack frame.
The printf statement is a function call. The printf function takes a variable length argument
list. Based on the first argument – the format string – the rest of the arguments are “interpreted”.
Here the format string (“%d”) indicates that it should read the second argument and interpret it as
an integer. The printf takes variable length argument list as argument and the compiler has no
knowledge about the internal affairs of routines like printf, so, it will happily compile the code
without complaining (but a tool like Lint will warn, but that’s a different story).
The compiler generates code for invoking printf. Conventionally, a compiler would generate
code to pass the arguments in the processor registers. For Unix/Linux, the code for printf will
be in a shared library (typically named as libc). That printf code, with “%d” as argument expects
an integer to follow it. It has code to read the argument from a processor register. It happens that
most of the compilers generate code by reusing the same registers (for example, an accumulator
register in processors that are accumulator based). So, it is likely that the same register that is
used for initializing the value of i is reused for reading the argument passed to printf. So 10 it
might get printed! Yes, compilers differ considerably in ways in which they generate code, but
they are also similar in many ways in which they make use of the processor resources. So, it is not
pure coincidence if you get 10 printed even when you try different compilers (even in different
If you are not convinced with my explanation, (1) try out this code in different platforms (by
platform, I mean a microprocessor, operating system and compiler combination) (2) take a look
at the generated assembly code by different compilers for small pieces of code like this. Even if
this program doesn’t work and print 10 in your platform, there is much to learn from this
Now let us discuss one more aspect on local variables. If you declare some local variables, they
would typically be allocated contiguously in the stack. Try this:
int i = 0, j = 10, k = 0;
int *p = &j;
*(p - 1) = 10;
*(p + 1) = 10;
printf(quot;i = %d j = %d k = %dquot;, i, j, k);
// most compilers will print
// i = 10 j = 10 k = 10
Here we attempt to check if the local variables i, j and k are contiguously allocated by modifying
local variables i and k through a pointer p which points to the address of j. It is most likely that
you’ll get values 10 for i, j and k. But things can go wrong also; for example, compilers can do
optimizations and can decide that i and k are not modified in the program and statically replace
i and k in printf with 0’s!
S.G. Ganesh is a research engineer in Siemens (Corporate Technology). He has
authored a book “Deep C” (ISBN 81-7656-501-6). You can reach him at