2

Are these two forms of array declaration correct?

First:

int n;
n=3;
int A[n];

Second:

#define N 300;
.
.
.
.
int a[N];

For me the two ways are totally valid, but someone told me the first is wrong.

The first one is like saying:

int A[10];

So, for me it doesn't make much sense to say that the first one is invalid.

But to be totally sure about it I wanted ask it here. Is it just about programing style or is the first one not a right way to do it?

Thank You.

Hydronium
  • 793
  • 1
  • 11
  • 28
exsnake
  • 1,767
  • 2
  • 23
  • 44

3 Answers3

6

Your first example uses a C99 feature called variable length arrays(VLA), this is covered in the draft C99 standard section 6.7.5.2 Array declarators paragraph 4:

[...] 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.

Neither form is necessarily bad but variable length arrays can be dangerous if their size can be controlled via user input. The main problem is that not all compilers support C99, the best example being Visual Studio which although recently started supporting parts of C99 as far as I know still does not support VLA. It is also a problem if you want to use your code in C++ as well since the C++ standard does not support VLA at all although but gcc and clang supports VLA as an extension in C++. Note that VLA was proposed for C++14 but was rejected.

Another issue is that C11 made VLA an optional feature, this is covered in the C11 draft standard section 6.10.8.3 Conditional feature macros:

_ _STDC_NO_VLA_ _   The integer constant 1, intended to indicate that the
                    implementation does not support variable length arrays or
                    variably modified types.
Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
2

As per C99 ISO variable length arrays are valid. The GCC manual says

Variable-length automatic arrays are allowed in ISO C99, and as an extension GCC accepts them in C90 mode and in C++

gcc:viarable-length

siu
  • 312
  • 1
  • 5
  • 10
1

Both variants have their pros and cons:


Advantages of Variable Length Arrays:

  • You do not waste memory. You can simply allocate as much memory as you need. This is most pronounced with strings: Usually, you want to allow for really long strings, even though most are really, really short. Allocating half a kilobyte for all strings is a huge waste of memory, even though allocating less might already be too tight a constraint.

  • You do not introduce artificial limits. Since you allocate precisely as much memory as is dynamically needed, you do not burden your users with upper limits on how long a name/path/file/whatever can be.

Disadvantages of Variable Length Arrays:

  • You cannot allocate arbitrarily large arrays on the stack. Even if your system can automatically grow your stack, you can still segfault your program by allocating an array that makes the stack pointer jump across the sentinel pages used by your OS. A few kilobytes is generally ok, a few megabytes is not.

Advantages of fixed size buffers:

  • Easy to set up.

  • They are C++. The C++11 standard explicitly disallows an array type from having a runtime size, even though C even allows you to typedef a variable length array since C99 (void foo(int n) { typedef int (*)[n]; ... } is perfectly legal C99, but you can't write void foo(int n) { int bar[n]; } in C++11).

Disadvantages of fixed size buffers:

  • They tend to burden the user with fixed limits. Sure, you can try to handle situations where you would normally need more memory, but in most cases, the limitations are just forwarded to the user who will be very unhappy about it one day.

  • They invite bugs via buffer overruns. You program needs to handle all errors due to exceeded array sizes explicitly and correctly. One mistake in this error handling code, and your program crashes in a way that is likely a security vulnerability. With variable length arrays, you never get into the situation of overrunning a buffer, because you always allocate your buffer large enough for the job.


All in all, I believe #define N ... and int foo[N]; is almost always bad style. If you can prove a low maximum size and you are not writing C++, go with Variable Length Arrays. If you can't malloc()/new the array. Only if you can prove that you can never require more than a very specific size (as in "a quartic root solver will never return more than four roots"), go ahead an use a fixed size. Personally, I allocate almost all arrays with malloc()/new.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106