1

Below are two methods which both work for creating an array, whose size is determined by user input.

I was always under the impression that data structures whose 'size' was determined by the user after compiling had to be created with malloc(). Example one illustarates this.

However, example two shows a much simpler method that does not require malloc().

Example #1: Create and array whose size is decided by a user input. Uses Malloc().

int main() {
  int N;

  printf( "Number:" );
  scanf( "%d", &N );

  int *ptr = createArray(N);

  for (int i = 0; i < N; i++) {
     printf("%d\n", ptr[i]);
  }

 free(ptr);
 return 0;
}

int *createArray(int N) {
  int *ptr = malloc(N);

  for (int i = 0; i < N; i++) {
    ptr[i]=N;
  }

  return ptr;
}

Example #2: Create and array whose size is decided by a user input. Does NOT use Malloc().

int main() {

  int N;

  printf( "Number:" );
  scanf( "%d", &N );

  int arr[N];

  for (int i = 0; i < N; i++) {
     arr[i] = N;
  }
  for (int i = 0; i < N; i++) {
     printf("%d\n",arr[i] );
  }

  return 0;
}

My question is, why is malloc() not needed for example 2, even though the program does not know the array size at the time of compiling?

seamus
  • 2,681
  • 7
  • 26
  • 49
  • 1
    See [this](https://stackoverflow.com/questions/16672322/malloced-array-vs-variable-length-array) and [that](https://softwareengineering.stackexchange.com/questions/279565/what-is-vla-and-how-it-is-implemented). – s7amuser Apr 09 '18 at 11:15
  • What is easier in it? There is a huuuuge difference. malloc allocates space on the heap and the declaration in the function on the stack - which is usually considerable smaller. – 0___________ Apr 09 '18 at 11:20
  • `scanf()` need not assign N if the input is not interpretable as a decimal integer - leaving it dangerously undefined. You should check the success of `scanf()` and impose limits on the value of N ( i.e. > 0, and not large enough to be likely to cause `arr` allocation to fail). – Clifford Apr 09 '18 at 11:32
  • 1
    The other reason why why is malloc() not needed for example 2 is that the lifetime of the array is not required to exceed the lifetime of the function, (it being just main). If an extended lifetime is required, the VLA is useless. – Martin James Apr 09 '18 at 11:43
  • Note that the `malloc()` code only allocates about 1/4 of the required memory. You should be using `int *ptr = malloc(N * sizeof(*ptr));` or equivalent. – Jonathan Leffler Apr 09 '18 at 13:03
  • Note that it saves everybody time and effort if you provide an MCVE ([MCVE]) — or, in this case, 2 MCVEs. That way we can ignore what you already know but didn't demonstrate that you know in the current version of this question. It should be as simple as possible, but no simpler (paraphrasing Einstein). – Jonathan Leffler Apr 09 '18 at 13:05

1 Answers1

4

Example 2 uses a variable length array (VLA), introduced at C99.

Accepting user input for a VLA without constraint is dangerous; malloc() will fail and return NULL if there is insufficient heap. VLA's on the other have no defined means to handle or indicate failure, and are typically allocated from more limited stack space.

On the other hand VLAs are true arrays and sizeof(arr) evaluates to the size of the array, not the size of a pointer (and is specifically not a compile-time constant).

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • Note that support for VLA is optional since C11. – Klas Lindbäck Apr 09 '18 at 11:38
  • 1
    Note that C99 _requires_ VLA support, then C11 made them _optional_. They were always best avoided for portability between C90 and C99, but now even more so. The option was probably added to allow compilers for small-memory embedded targets to claim compliance without having to implement unnecessary and dangerous VLA support, but they were not made optional on certain types of system - that would be problematic - they are universally optional, so arguably best avoided (as they always were IMO - as an embedded systems developer). – Clifford Apr 09 '18 at 11:41
  • 4
    What the committee failed miserably to see was that while VLAs have limited use in some applications - certainly in embedded - _pointers_ to VLA are far more useful. For example writing a function like `void func (size_t n, int arr[n])` is more type safe than `void func (int* arr, size_t n)`. Similarly, code such as `int (*arr)[Y] = malloc( sizeof(int[X][Y]) );` is much more elegant than ugly C90 "mangled arrays: `int* arr = malloc(x*y*sizeof(int))`. Making VLA optional is therefore a shortcoming by the committee, since it also makes pointer to VLA optional. – Lundin Apr 09 '18 at 11:57
  • 1
    Out of curiosity, is there a compiler (by Microsoft, perhaps?) that claims conformance to C11 (`__STDC_VERSION__` set to `201112L`) but which defines `__STDC_NO_VLA__` (indicating that it does not support VLAs)? Is there a compiler that has most of C11 support without claiming full compliance that does not support VLAs? (GCC on a Mac does not have `` or ``, but does have most of the rest of C11.) – Jonathan Leffler Apr 09 '18 at 13:11
  • @JonathanLeffler If any compiler would ever use that, it would probably be some of the crappier ones for embedded. As things stand currently, only a few of the good embedded compilers support C11 and they support VLAs too. As for Microsoft, they are still struggling with the 19 year old C99 standard. – Lundin Apr 09 '18 at 13:38