5

I was reading about creating array dynamically in C. So the proper way as described there was:

int n;
scanf("%d", &n);
int *arr = (int*)malloc(n*sizeof(int));

But then I thought if I could just do something like this-

int n, i, sum=0;
scanf("%d", &n);
int arr[n];

And I compiled and ran it without any error. So, my question is why should I use malloc()? Does this have something to do with the old and new C versions?

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
Farhan Fuad
  • 189
  • 2
  • 12
  • You can't resize your static array, but you can resize what you allocate on the heap with `realloc`. – Christian Gibbons Jul 20 '18 at 18:17
  • 1
    Be careful with `scanf`. What happens if you type in `-10`? – tadman Jul 20 '18 at 18:20
  • Another thing you'll *quickly* learn about C is that just because something compiles is absolutely no indication as to if it will work. *Undefined behaviour* is a constant problem if you're not paying close attention to what you're doing and are aware of the consequences of your coding decisions. – tadman Jul 20 '18 at 18:22
  • 2
    The duplicate answer is about C99 but in C11 variable length arrays are "optional" whatever you might think about the merits or politics of that decision. So portable code doesn't use the VLA. – Weather Vane Jul 20 '18 at 18:23
  • "... and run it without any error" did you enter a small number like 42? Try something like 42000000 and see if it runs without "error". – chux - Reinstate Monica Jul 20 '18 at 18:24
  • Interesting. Process terminates. Sorry I am a newbie, could you please explain why should I be careful with `scanf()` ? Besides that's a negative integer. I am not really sure what array[-10] means to the compiler. @tadman – Farhan Fuad Jul 20 '18 at 18:24
  • More relevant is passing a negative value to an unsigned argument for `malloc`. It won't do anything sensible. – Weather Vane Jul 20 '18 at 18:25
  • It means "please go poke around in the memory of another process" and the OS is generally quick to block that and terminate your process immediately. It's an invalid memory location. This is why you need to be careful in C. It will let you *try* and do a lot of things that are blatantly disallowed, but the OS will intervene and shut it down. As they say: "C gives you enough rope to shoot yourself in the foot". If you didn't know you could shoot yourself in the foot with rope you should've read the manual more closely. – tadman Jul 20 '18 at 18:27
  • Why should you be careful with `scanf`? a) you should check that the function "worked" successfully, for example you enter `Z`, and b) you should check the value entered is within the bounds you want to use. – Weather Vane Jul 20 '18 at 18:28
  • Yes, that's obviously to be careful with in general. I thought he meant there were alternative safer functions available (?) @WeatherVane – Farhan Fuad Jul 20 '18 at 18:31
  • 1
    Yes, you are right, with bigger numbers the process is terminating unlike for `malloc()` @chux – Farhan Fuad Jul 20 '18 at 18:32
  • @FarhanFuad please don't ask a question and then say "that's obvious", when your code snippet makes no suggestion that you take such precautions. – Weather Vane Jul 20 '18 at 18:33
  • I am sorry, my bad. I didn't mean any disrespect @WeatherVane – Farhan Fuad Jul 20 '18 at 18:35
  • 1
    It is easier to recover from bad input if you use `fgets` and apply `sscanf` to that. – Weather Vane Jul 20 '18 at 18:40
  • @EricPostpischil - I think your suggestion to reopen is good as there are useful points made here that would benefit from expanding into answers. I've voted to re-open. Can you also? – ryyker Jul 20 '18 at 18:52
  • @WeatherVane - You make some good points in discussion. Please put in answer. (vote to reopen per Eric's suggestion) – ryyker Jul 20 '18 at 18:54
  • 1
    @ryyker I posted an answer in that [reopened question](https://stackoverflow.com/questions/6629394/variable-length-vs-malloc-ed-arrays/51449634#51449634). – Weather Vane Jul 20 '18 at 20:11
  • I actually thought this question would be re-opened, but in any case, you offered some new, and useful information about using VLAs (one of my favorite things in recent couple of years) that I had not considered before. (+1 for that post) – ryyker Jul 20 '18 at 21:40

2 Answers2

13

There are at least five benefits to using malloc over variable length arrays.

  1. Most notably, objects created with malloc persist after execution of the current block ends. This means that such objects can be returned (by pointer) to callers of functions. This use is frequent in real-world applications. Arrays created as variable-length arrays cease to exist when execution of their block ends.

  2. Arrays created with malloc can be resized with realloc. Variable-length arrays cannot be resized.

  3. As of the 2011 C standard, variable-length arrays are optional for C implementations to support. A general-purpose C implementation of any quality will support them, but the fact they are optional means code that is intended to be portable must either not use variable-length arrays or must guard against the lack of support by testing the preprocessor macro __STDC_NO_VLA__ and providing alternate code.

  4. Commonly, variable-length arrays are much more limited in size than arrays allocated with malloc. Variable-length arrays are generally implemented using stack space, and stacks are typically limited to some not-large number of mebibytes (although that can generally be increased when building an executable). For objects created with malloc, gibibytes of memory may be available in modern systems.

  5. If creation of an array does fail with malloc, NULL will be returned, and the programmer can easily write code to detect that and deal with it. If creation of a variable-length array fails, the common behavior is for the operating system to terminate the program with some memory error. (Various C implementations may provide means to intercept this error, but it is considerably more of a nuisance than testing the malloc return value for NULL, and it is not portable.)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
2

And I compiled and run it without any error. So, my question is why should I use malloc() really? Does this have something to do with the old and new C versions?

Stack-allocated arrays are not equivalent to buffers in the free-store (the heap, the memory area that malloc and calloc use).

  1. Assuming the array exists on the stack (which is implied as an automatic-variable) then your array cannot exceed the maximum stack size for your platform. On Linux with pthreads the default is 2 megabytes. The limit is similar on Windows.

  2. Because of scope and object lifetime: pointers to elements in an array that exist on the stack cannot live longer than the array they point into, which means you cannot return pointers to those arrays and elements after the scope they're declared in expires.

  3. VLA arrays are optional in C11. In C++ they're not part of the spec at all (i.e. they're vendor extensions) so your code won't be portable.

Dai
  • 141,631
  • 28
  • 261
  • 374