21

I've always wondered how I could get away with this:

int main(int argc, char **argv) {
    printf("%p %s %d\n", &argv[1], argv[1], strlen(argv[1]));
    char copy[strlen(argv[1]) + 1];
    strcpy(copy, argv[1]);
    printf("%p %s %d\n", &copy, copy, strlen(copy));
    return 0;
}

The char array copy gets allocated anyway and the program runs fine, printing out the original and the copy. And Valgrind doesn’t complain about anything.

I thought dynamic arrays weren’t possible in C without malloc. Was I wrong?

Palec
  • 12,743
  • 8
  • 69
  • 138
lt0511
  • 213
  • 1
  • 2
  • 4

4 Answers4

19

This is a C99 feature and could be implemented on prior versions by the compiler.

Variable-length automatic arrays are allowed in ISO C99, and as an extension GCC accepts them in C90 mode and in C++. These arrays are declared like any other automatic arrays, but with a length that is not a constant expression. The storage is allocated at the point of declaration and deallocated when the brace-level is exited.

Joe
  • 56,979
  • 9
  • 128
  • 135
7

Variable-length arrays originated as a GCC extension, but they were also adopted by C99.

They are still being allocated on the stack, so making them "huge" is considered bad style (and will likely break on you someday).

Nemo
  • 70,042
  • 10
  • 116
  • 153
  • Wow. It has been so long since I've used plain C (or gcc for that matter), that I have completely missed this becoming standard. – Dima Jul 11 '11 at 21:29
  • @Dima: Truth me told, I forgot myself until I re-read the description in the GCC manual :-). (I never use this feature; dynamic stack usage is just too dangerous.) – Nemo Jul 11 '11 at 21:33
  • @Nemo: so long as you know the stack limits on your target platform, and take them into account, I don't see it as dangerous. – Stephen Canon Jul 11 '11 at 21:35
  • 1
    @Stephen: In my experience, the code always outlives the "target platform". (Put another way, the eventual target platform is never as known as you think it is.) Also there are great static checkers (Coverity) that can compute a bound on the program's _total_ stack consumption, but probably not in the presence of stuff like this. So in general I think this gadget is best avoided. (Of course every rule has an exception.) – Nemo Jul 11 '11 at 21:41
  • I agree with both of your arguments; I often use recursion to effect both simple and convenient solutions, but large indefinite stack patterns certainly warrant additional consideration. – Taliadon Jul 11 '11 at 23:49
3

Even before the existence of "variable length arrays," courtesy gcc and C99, there was:

alloca() -- which allows dynamic allocation of stack ("automatic") memory.

Heath Hunnicutt
  • 18,667
  • 3
  • 39
  • 62
  • According to the BSD man page for alloca, it was introduced in Version 32V AT&T Unix (1979). So it has been around a while. – ldav1s Jul 12 '11 at 00:21
  • [alloca is evil](http://stackoverflow.com/questions/1018853/why-is-alloca-not-considered-good-practice) when allocating possibly large ammounts of memory. – Vorac Jan 07 '14 at 11:14
  • 1
    @Vorac -- thanks for the input, but that's not really true. Have you personally given it a shot? The amount of stack normally available to a program is much, much, much, more than "a few hundred bytes." Obviously, we always need to be aware of machine limitations, but to assume alloca() is more limited that sbrk() doesn't make a lot of sense, really. – Heath Hunnicutt Jan 12 '14 at 21:31
2

"Variable length arrays" were added to the C language in C99. This is covered in §6.7.5.2 "Array declarators":

If the size is an expression that is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by *; otherwise, each time it is evaluated it shall have a value greater than zero. The size of each instance of a variable length array type does not change during its lifetime. Where a size expression is part of the operand of a sizeof operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated.

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269