22

Will it be precise to say that in

void f() {
    int x;
    ...
}

"int x;" means allocating sizeof(int) bytes on the stack?

Are there any specifications for that?

5 Answers 5

23

Nothing in the standard mandates that there is a stack. And nothing in the standard mandates that a local variable needs memory allocated for it. The variable could be placed in a register, or even removed altogether as an optimization.

5
  • Ok. So the safest thing to do is to not assume that memory gets allocated for declared variables. But when do we know for sure that memory gets allocated for a variable (Besides explicit calls to allocate memory on the heap)? When variables are initialized?
    – Minh Tran
    Commented Jan 4, 2017 at 4:58
  • Why do you ask. What problem are you trying to solve. Commented Jan 4, 2017 at 7:03
  • Suppose I use typedef to define a struct and declare an instance of that struct inside a function without initializing its member. According to your answer, what happens in the stack depends on compiler implementation. However, if we instead initialized the struct (say with a designated initializer), does the compiler allocate memory for that instance on the stack?
    – Minh Tran
    Commented Jan 4, 2017 at 22:19
  • 1
    There might not be a stack. At all. Commented Jan 4, 2017 at 22:19
  • Ah. I'm a little confused since some of the text and articles I've read refer to the space where local variables are stored (in virtual memory within an "activation record") as a stack, which suggest there is a stack.
    – Minh Tran
    Commented Jan 4, 2017 at 22:32
8

There are no specification about that and your assumption is often (but not always) false. Consider some code like

void f() {
   int x;
   for (x=0; x<1000; x++) 
     { // do something with x 
     }
   // x is no more used here
}

First, an optimizing compiler would put x inside some register of the machine and not consume any stack location (unless e.g. you do something with the address &x like storing it in a global).

Also the compiler could unroll that loop, and remove x from the generated code. For example, many compilers would replace

for (x=0; x<5; x++) g(x);

with the equivalent of

g(0); g(1); g(2); g(3); g(4);

and perhaps replace

for (x=0; x<10000; x++) t[x]=x;

with something like

for (α = 0;  α < 10000;  α += 4) 
  { t[α] =  α; t[α+1] =  α+1; t[α+2] =  α+2; t[α+3] =  α+3; };

where α is a fresh variable (or perhaps x itself).

Also, there might be no stack. For C it is uncommon, but some other languages did not have any stack (see e.g. old A.Appel's book compiling with continuations).

BTW, if using GCC you could inspect its intermediate (Gimple) representations with e.g. the MELT probe (or using gcc -fdump-tree-all which produces hundreds of dump files!).

2
  • There is indeed nothing in the C standard mentioning the stack. But whether there is a stack or not depends on the CPU, not on the programming language. If a CPU has push/pop instructions and a stack pointer, it has a stack, of a size defined by software. Though a particular compiler may of course choose not to use those stack instructions (which would be stupid). My point is: how a compiler translates the high level language to CPU instructions has little to do with the language itself.
    – Lundin
    Commented Sep 17, 2013 at 7:36
  • 3
    No, a compiler could have an ABI which does not use the machine stack. A compiler could also target some bytecode VM (and the interpreter of that VM won't use a lot the machine stack) And some C interpreters don't use the machine stack that much. Commented Sep 17, 2013 at 7:37
6

from GNU:

3.2.1 Memory Allocation in C Programs

Automatic allocation happens when you declare an automatic variable, such as a function argument or a local variable. The space for an automatic variable is allocated when the compound statement containing the declaration is entered, and is freed when that compound statement is exited. In GNU C, the size of the automatic storage can be an expression that varies. In other C implementations, it must be a constant.

1
  • 1
    This is a nice citation, but it's demonstrably wrong, since variables are quite often optimized out. Commented Sep 17, 2013 at 7:26
2

It depends on a lot of factor. The compiler can optimize and remove it from the stack, keeping the value in register. etc.

If you compile in debug it certainly does allocate some space in the stack but you never know. This is not specify. The only thing specify is the visibility of the variable and the size and arithmetic on it. Look at the C99 spec for more information.

0

I think it depends on compiler. I used the default compiler for Code::Blocks and Dev-C++ and it looks like memory is allocated during initialization. In following cout statement, changing n2 to n1 will give the same answer. But if I initialize n1 to some value, or if I display n2 before I display the average, I will get a different answer which it is garbage. Note that VS does correctly handles this by giving error since variables are not initialized.

void getNums();
void getAverage();

int main()
{
    getNums();
    getAverage();

    return 0;
}
void getNums()
{
    int num1 = 4;
    double total = 10;
}
void getAverage()
{
    int counter;
    double n1 , n2;
    cout << n2/counter << endl;
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.