Search code examples
c++arraysgccvariable-length-array

Are gcc's dynamically-sized arrays effectively identical to standard arrays after declaration?


In standard C and C++ the address of an array is the array itself, and sizeof returns the size of the array, not the pointer. However, does gcc's extension of dynamically-sized arrays offer the same guarantee?

I tried this simple code:

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

int main(int argc, char ** argv)
{
    char foo[200];
    char bar[atoi(argv[1])];
    char *wibble = foo;

    printf("%p, %p, %lu, %p, %p, %lu, %p, %p, %lu\n",
           foo, &foo, sizeof(foo), bar, &bar, sizeof(bar), wibble, &wibble, sizeof(wibble));

    return 0;
}

The output is as I hoped, indicating equivalence:

0x7ffc7dd132e0, 0x7ffc7dd132e0, 200, 0x7ffc7dd131e0, 0x7ffc7dd131e0, 200, 0x7ffc7dd132e0, 0x7ffc7dd132c8, 8

However, is this equivalence guaranteed by gcc? Are there any times where using a dynamically-sized instead of a statically-sized array will result in different program behaviour?

※ Note I'm interested in if it works, not how to write it better using std::vector, etc


Solution

  • Straight from the ISO C99 doc, page 80:

    The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.

    So the answer to your first question is that it's guaranteed by the C99 standard, which gcc presumably follows.

    As for whether there are times it'll behave differently from a statically sized array well...not if you're using them sanely.

    While I can't find record of this in ISO C99, it appears that gcc always puts a VLA on the stack - which makes sense because it's essentially an alloca(), and is intended to go out of scope at the end of the block. Used sanely, there should never be any difference between how a dynamically sized array behaves and how a statically sized array behaves. Used insanely however, yes there could be extreme corner cases for exploitation (or other hacky) behavior where a person doing exploitation might be happy to discover you're using one over the other.

    Regardless, you can probably feel comfortable using whichever one you feel comfortable with. Usually, (for one or two reasons of varying justifiability) programmers prefer malloc over stack allocations.