tags:

views:

180

answers:

3

I have a situation where I want my program to read in some numbers that will define the size of a two dimensional array (used as a matrix). I originally argued that the only way to do this would be to use a malloc call to put the array on the heap, something like this:

matrixElement* matrix = malloc(sizeof(matrixElement) * numRows * numCols);

where numCols and numRows are the integers which were read in earlier, and matrixElement is some arbitrary type. My reasoning was that simply writing:

matrixElement matrix[numRows][numCols];

would not work since the compiler would have no way of knowing how much stack space to allocate to the function call. It turns out I was wrong, since the following code compiles and runs:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int x, y;
    scanf("%d", &x);
    scanf("%d", &y);

    double arr[x][y];

    printf("Made an array of size %d by %d, total memory %fKb\n", 
      sizeof(arr) / sizeof(arr[0]), 
      sizeof(arr[0]) / sizeof(arr[0][0]),
      (float) sizeof(arr) / 1024.0f);

    return 0;
}

With big enough numbers input for x and y, this will eventually give a segfault, but I was very surprised too see that I could create a 1000x1000 array with this code.

Can anyone explain what is going on here?

Is the compiler just allocating a bunch of space for the array, even though it has no idea how much will be used?

Is this behavior specified by ANSI C or is it just something that gcc is doing on its own?

+8  A: 

This feature was added in C99. The array is allocated on the stack similarly to how it would have been if you had called alloca(). There may be some subtle differences; check your compiler documentation for information.

The GCC documentation has a description of their implementation.

Carl Norum
But be aware that support for this is pretty spotty. Even in GCC which has tried to support it for a while now, it's apparently been pretty buggy even up through version 4.3 (http://gcc.gnu.org/gcc-4.3/c99status.html)
Michael Burr
+1, absolutely true. It's probably the most controversial addition of C99.
Carl Norum
Note that your stack is usually much smaller than your heap. If you want dynamically sized arrays of any real size, using malloc() is probably a good idea. Also remember that like all local (non-static) objects, these arrays disappear once your function has returned.
Variable Length Coder
+3  A: 

C99 added support for variable length arrays (sometimes called "VLAs"). Many C compilers also had support for this prior to C99. Many also supported an "alloca" function, that did the same thing, though in a slightly less convenient way.

Typical implementations allocate the "correct" amount of space. Essentially, the stack pointer is just adjusted based on the size of your variable length array. Some extra book keeping needs to be done to ensure that the stack pointer is "popped" the right amount upon returning, and that auto variables placed on the stack are accessed at the correct offset.

Laurence Gonsalves
+3  A: 

You should be as much surprised by the fact that you can declare your arr array in the middle of the block, as you are surprised by its variable-specified size. Both are new features of C99 language specification. Both were supported by GCC compiler as an extension to C89/90 for a while. But neither is legal in "classic" ANSI C, i.e C89/90.

If you are compiling your code in C89/90 mode (which is default in GCC), then you are indeed dealing with something GCC is doing on its own accord. If you are compiling your code in -std=c99 mode, you are dealing with [relatively] new standard languages features.

AndreyT
Except that 'declarations anywhere' are much more commonly seen as extensions to C90 and in C++ code, while VLAs are not so commonly seen.
Michael Burr