1

Is it safe to write code like below?

void func(int v[], int size) {
 int array_local[size];

 for(int i = 0; i < size; i++) array_local[i] = v[i];

 /*
 Other stuff...
 */

}

Or could I stumble upon some kind of error?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
user8469759
  • 2,522
  • 6
  • 26
  • 50
  • 1
    Depends on what you do and also on the value of `size`. Nothing in the given code is wrong though. – Spikatrix May 18 '15 at 12:04
  • 1
    Note, that variable length arrays are stored on the stack and you have limited stack space so this case be an issue. Also note if you want the code code to be portable [VLA is a C99 feature](http://stackoverflow.com/a/16588397/1708801) and [until recently Visual Studio did not support C99](http://stackoverflow.com/q/27826409/1708801) and as far as I know variable length arrays are still missing. – Shafik Yaghmour May 18 '15 at 12:09
  • 1
    It is OK in C99, as long as the size is small enough not to overflow the stack. You would be better off with `size` of type `size_t`. – Sergey Kalinichenko May 18 '15 at 12:09

4 Answers4

2

It is safe as long as the caller ensures that v has at least size elements, otherwise of course it will cause problems, you don't have to worry about that, because you can't do anything about it anyway.

You also have to be careful not to return array_local, because it will be deallocated when the function returns, since it's allocated in the function stack frame.

Also, the above code is not necessary to copy the array, you could just

memcpy(array_local, v, size * sizeof(int));
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • Size is a parameter. He's already making sure the caller specifies the size of the local array. – SBI May 18 '15 at 12:06
  • 1
    I figured as much, but then you should write that `v` must have at least `size` elements. `array_local` automatically does. – SBI May 18 '15 at 12:08
2

Yeah this is perfectly fine and valid on and above C99. It is called VLA.

To be on safer side, you should put a check on the value of size before using it as the number of elements of the array. As you've got the size defined as int, you should prohibit passing a value of say -5 to size.

That said, for the remaining part of the code (as a general suggestion)

  1. v[i] should not cause in memory overrun.
  2. The array is local to the function. You should never try returning the address of the array (Either through a pointer or through return statement).
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Could i potentially declare a double sized array, something like "int array_local[2*size]"? – user8469759 May 18 '15 at 12:20
  • @Lukkio yeah, certainly you can, provided 1) the suggested checks on `size` are done. and 2) the `2* size` does not cause stackoverflow. :-) – Sourav Ghosh May 18 '15 at 12:21
1

This is called a Variable Length Array, and they only exist in C99. So as long as your compiler supports the -c99 compilation flag, and you are using it, the code is valid.

As for whether or not you should use it, that depends on how large you expect size to be. With stack allocation, you have no protection against allocating too much memory. If you were to use a dynamic allocator, like malloc, you could check for a NULL return value, whereas with a VLA, you will just blow the stack if you ask for too much. If size will be small, there is no problem with it.

Bradley Garagan
  • 155
  • 1
  • 9
1

You can implement same thing in other way using dynamic memory allocation and is safe to be implemented:

void func(int v[], int size) {
 int *array_local = (int*)malloc(sizeof(int) * size);

 for(int i = 0; i < size; i++) *(array_local + i) = *(v + i);

 /*
 Other stuff...
 */

}
Rahul Raina
  • 3,322
  • 25
  • 30
  • other than 1) in C, do not cast the returned value from malloc (and family) 2) always check (!=NULL) the returned value to assure the operation was successful. I've been using this form since first working with C, some 30 years ago. – user3629249 May 19 '15 at 22:02
  • Agreed with point 2. But in point 1: if you will not typecast the return of malloc how will you assign the memory to pointer. Compiler will also give error for that. Typecast isn't needed in case of void* only. – Rahul Raina May 20 '15 at 02:39