user2738599
user2738599

Reputation: 81

If I define an array in if statement then does memory get allocated?

If I define an array in if statement then does memory gets allocated during compile time eg.

if(1)
{
    int a[1000];
} 
else
{
    float b[1000];
}

Then a memory of 2 * 1000 for ints + 4 * 1000 for floats get allocated?

Upvotes: 8

Views: 2860

Answers (5)

bazza
bazza

Reputation: 8414

Scope

Variables declared inside the scope of a pair of { } are on the stack. This applies to variables declared at the beginning of a function or in any pair of { } within the function.

int myfunc()
{
   int i = 0;   // On the stack, scoped: myfunc

   printf("%i\n");

   if (1)
   {
       int j = 1;   // On the stack, scope: this if statement

       printf("%i %i\n",i,j);
   }

   printf("%i %i\n",i,j);   // Won't work, no j
}

These days the scope of the variables is limited to the surrounding { }. I recall that some older Microsoft compilers didn't limit the scope, and that in the example above the final printf() would compile.

So Where is it in memory?

The memory of i and j is merely reserved on the stack. This is not the same as memory allocation done with malloc(). That is important, because calling malloc() is very slow in comparison. Also with memory dynamically allocated using malloc() you have to call free().

In effect the compiler knows ahead of time what space is needed for a function's variables and will generate code that refers to memory relative to whatever the stack pointer is when myfunc() is called. So long as the stack is big enough (2MBytes normally, depends on the OS), all is good.

Stack overflow occurs in the situation where myfunc() is called with the stack pointer already close to the end of the stack (i.e. myfunc() is called by a function which in turn had been called by another which it self was called by yet another, etc. Each layer of nested calls to functions moves the stack pointer on a bit more, and is only moved back when functions return).

If the space between the stack pointer and the end of the stack isn't big enough to hold all the variables that are declared in myfunc(), the code for myfunc() will simply try to use locations beyond the end of the stack. That is almost always a bad thing, and exactly how bad and how hard it is to notice that something has gone wrong depends on the operating system. On small embedded micro controllers it can be a nightmare as it usually means some other part of the program's data (eg global variables) get silently overwritten, and it can be very hard to debug. On bigger systems (Linux, Windows) the OS will tell you what's happened, or will merely make the stack bigger.

Runtime Efficiency Considerations

In the example above I'm assigning values to i and j. This does actually take up a small amount of runtime. j is assigned 1 only after evaluation of the if statement and subsequent branch into where j is declared.

Say for example the if statement hadn't evaluated as true; in that case j is never assigned 1. If j was declared at the start of myfunc() then it would always get assigned the value of 1 regardless of whether the if statement was true - a minor waste of time. But consider a less trivial example where a large array is declared an initialised; that would take more execution time.

int myfunc()
{
   int i = 0;           // On the stack, scoped: myfunc
   int k[10000] = {0}   // On the stack, scoped: myfunc. A complete waste of time
                        //  when  the if statement evaluates to false.

   printf("%i\n");

   if (0)
   {
       int j = 1;   // On the stack, scope: this if statement

       // It would be better to move the declaration of k to here
       // so that it is initialised only when the if evaluates to true.

       printf("%i %i %i\n",i,j,k[500]);

   }

   printf("%i %i\n",i,j);   // Won't work, no j
}

Placing the declaration of k at the top of myfunc() means that a loop 10,000 long is executed to initialise k every time myfunc() is called. However it never gets used, so that loop is a complete waste of time.

Of course, in these trivial examples compilers will optimise out the unnecessary code, etc. In real code where the compiler cannot predict ahead of time what the execution flow will be then things are left in place.

Upvotes: 1

Ziffusion
Ziffusion

Reputation: 8923

In your example, only the memory for the ints gets allocated on the stack (1000 * sizeof(int)).

As you can guess, this is happening at run time. The generated code has instructions to allocate the space on the stack when the corresponding block of code is entered.

Keep in mind that this is happening because of the semantics of the language. The block structure introduces a new scope, and any automatic variables allocated in that scope have a lifetime that lasts as long as the scope does. In C, this is implemented by allocating it on the stack, which collapses as the scope disappears.

Just to drive home the point, note that the allocation would be different had the variables been of different nature.

if(1)
 {
  static int a[1000];
 } 
else
 {
  static float b[1000];
 }

In this case, space is allocated for both the ints and the floats. The lifetime of these variables is the program. But the visibility is within the block scope they are allocated in.

Upvotes: 1

0xF1
0xF1

Reputation: 6116

As DCoder & paddy corrected me, the memory will be calculated at compile time but allocated at run-time in stack memory segment, but with the scope & lifetime of the block in which the array is defined. The size of memory allocated depends on size of int & float in your system. Read this for an overview on C memory map

Upvotes: 0

user1814023
user1814023

Reputation:

Memory for the array in the if block will be allocated on stack at run time. else part will be optimized (removed) by the compiler. For more on where the variables will be allocated memory, see Segmentation Fault when writing to a string

Upvotes: 0

paddy
paddy

Reputation: 63481

It is reserved on the stack at run-time (assuming a non-trivial condition - in your case, the compiler would just exclude the else part). That means it only exists inside the scope block (between the {}).

Upvotes: 4

Related Questions