0

Whenever I need to create an array with a number of elements not known until execution time I do this.

int n, i;
printf("Number of elements: ");
scanf("%d", &n);
int myArray[n];
for(i = 0; i < n; i++)
    myArray[i] = 0;

However I've been told by 3 people with a PhD in Computer Science not to do it, because "it's not guaranteed to work on every compiler", and that the number of the elements in an array must be known at compile-time. So they do that like this.

int myArray[1000];
int n, i;
printf("Number of elements: ");
scanf("%d, &n);
//we must stop at the n element
for(i = 0; i < n; i++)
    myArray[i] = 0;

Which one should I use? When it's not guaranteed to work? Is it just a memory waste or a need to maintain legacy?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Use dynamic memory allocation if you want to implement dynamic arrays in C. – clarasoft-it Jul 29 '16 at 19:21
  • 3
    Neither. Use something like `int * myArray = malloc( n * sizeof *myArray);` and do your cleanup later when finished. – WhozCraig Jul 29 '16 at 19:22
  • It is completely compiant to the C99 version of the standard. It is called variable length array (VLA). Due to some unknow reason, the commitee made VLAs optional in the current version (C11) - against their established practice of backwards-compatibility at all cost. I'd still recommend to use it. A modern desktop compiler will support it (e.g. gcc and clang). Don't use outdated compilers like MSVC. They have other problems with modern C, too. Sometimes one has to make a cut. WQe don't use horse-cariages either anymore. Or morse emails. Your PhDs should move on – too honest for this site Jul 29 '16 at 19:58
  • @clarasoft-it: A VLA is not a dynamically allocated array, but a normal automatic variable. – too honest for this site Jul 29 '16 at 20:19
  • Just in case my comment was not clear: Use VLAs, but make sure they will not overflow the stack (as for any other automatic variable!). Use modern compilers, no outdated rubbish from vendors who sell them for some 1k bucks/euros/etc. without going forward. – too honest for this site Jul 29 '16 at 20:22

2 Answers2

1

"it's not guaranteed to work on every compiler"

Yes, basically, correct.

The first approach, VLA, variable length array, was a part of C99 standard. However,

  • in C11, that has been made optional. You better not rely on that feature.
  • C89 did not have that as a port of the standard. gcc extensions were there, however, to support them.

Quoting C11, chapter §6.7.6.2/p5

[....] If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays are a conditional feature that implementations need not support; see 6.10.8.3.)

As an alternative approach, you can always use a pointer and dynamic memory allocation like malloc() and family, if you have to rely on run-time values.

Taken together, to answer the question

Is creating array with a variable number of elements possible?

It is possible, but only with VLA support. Without that, you have to sate yourself with a pointer and memory allocation functions, at best.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Hi Sourav! I stongly disagree with your conclusion not to use VLAs. Just because there's still people using horse-carriages does not mean all motorways shall have a speed-limt of 20 km/h. There are enough modern compilers which do support C99, thus VLAs. Compilers which do not support C99/full C11 likely don't support other features, too in modern C. C seems to be the only alnguage stuck to a 27 year old version just because people refuse to learn something new and request modern featurres from their vendors. – too honest for this site Jul 29 '16 at 20:02
  • 1
    @Olaf Sir, thank you for the comments. First of all, I am not against VLAs, I just tried to suggest as _alternative_, as you can see. Secondly, I was trying to specify the compiler supports for each of them. If you think my answer in biased in any way, please suggest changes in wordings or feel free to modify. :) – Sourav Ghosh Jul 29 '16 at 20:06
  • Dynamic allocation is **not** a replacement for VLAs in general. Not only the functions are not available for most implementations - condidering most implementations are freestanding without the then not required parts of the standard library. Then they are not usable if you need multidimensional arrays, because you need a pointer to VLA for 2D already if you use dynamic allocation.. – too honest for this site Jul 29 '16 at 20:14
  • @Olaf You're very correct. Replacement, no. Alternative approach, yes. In case, VLAs are not around (not supported), then we have to work around them using pointer and `malloc()`, don't you agree? Also, VLAs are stack-size limited, at least in `gcc`, while `malloc()` is probably more generous. :) – Sourav Ghosh Jul 29 '16 at 20:22
  • No, the work-around is to drop support for rubbish (and often expensive) compilers. Might sound harsh, but that is the only way to put them under pressure. WIthout that C will never get out of the C90 depression. Re. stack size: is that different from fixed-size arrays or other variables or recursion? Sorry, but that is no argument against VLAs, but automatic variables in general (which you hopefully agree is pretty nonsense). Btw. the C standard does not mandate using a stack, you can very well allocate automatic variables using dynamic memory allocation. And the size is not compiler-specific – too honest for this site Jul 29 '16 at 20:29
1

If you want something that is C89 compliant and doesn't use too much memory, there is a third option which is to allocate memory dynamically:

int n, i;
printf("Number of elements: ");
scanf("%d", &n);
int *myArray = malloc(sizeof(int)*n);   // allocate space for n ints
if (myArray == NULL) {
    perror("malloc failed");
    exit(1);
}
for(i = 0; i < n; i++)
    myArray[i] = 0;

Just be sure to call free on the allocated memory when you're done with it.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • @dbush I always use pointers and malloc whenever I need to change the size dinamically, in this case I don't. When using MinGW with the c89 compiler flag it works the first way. Why should I use this instead? (what are the "benefits") –  Jul 29 '16 at 19:34
  • 1
    @Sheldon Using dynamic allocation is more portable. However if your compiler supports variable length arrays and you don't plan on migrating it, it has the advantage of not having to worry about freeing memory that's been allocated. – dbush Jul 29 '16 at 19:38
  • 1
    @KevinDTimm: `calloc` zeroes all bits. That is identical with the value `0` for integers only. Fine here, but not true for floating point or pointers. (It differs from default initialisers in this aspect, btw.) Just let the compiler figure out how to optimise that, A good compiler might use `memset`/`memclr` or even collapse both part into `calloc`. if that works. – too honest for this site Jul 29 '16 at 20:03
  • @Olaf - OP has declared an array of int, I'm solving his problem, not the problem of others. If he wanted a solution to a generic problem, I assume he would have asked. – KevinDTimm Aug 01 '16 at 12:53