There are tons of similar questions, but still I could not find any answer relevant for the feature of variable length arrays in C99/C11.
How to pass multidimensional variable length array to a function in C99/C11?
For example:
void foo(int n, int arr[][]) // <-- error here, how to fix? { } void bar(int n) { int arr[n][n]; foo(n, arr); }
Compiler (g++-4.7 -std=gnu++11
) says:error: declaration of ‘arr’ as multidimensional array must have bounds for all dimensions except the first
If I change it to int *arr[]
, compiler still complains:error: cannot convert ‘int (*)[(((sizetype)(((ssizetype)n) + -1)) + 1)]’ to ‘int**’ for argument ‘2’ to ‘void foo(int, int**)’
Next question, how to pass it by value and how to pass it by reference? Apparently, usually you don't want the entire array to be copied when you pass it to a function.
With constant length arrays it's simple, since, as the "constant" implies, you should know the length when you declare the function:
void foo2(int n, int arr[][10]) // <-- ok { } void bar2() { int arr[10][10]; foo2(10, arr); }
I know, passing arrays to functions like this is not a best practice, and I don't like it at all. It is probably better to do with flat pointers, or objects (like std:vector) or somehow else. But still, I'm a bit curios what is the answer here from a theoretical standpoint.
In this tutorial, we will learn how to pass a single-dimensional and multidimensional array as a function parameter in C++ with the help of examples. In C++, we can pass arrays as an argument to a function. And, also we can return arrays from a function.
The first one would be called like func1(foo, foo + CAPACITY) : passing in a pointer to the start of the array, and a pointer to just beyond the last element. The second would be called like func2(foo, CAPACITY) : passing in a pointer to the start of the array and the array size.
To pass an entire array to a function, only the name of the array is passed as an argument. result = calculateSum(num); However, notice the use of [] in the function definition. This informs the compiler that you are passing a one-dimensional array to the function.
The basic form of declaring a two-dimensional array of size x, y: Syntax: data_type array_name[x][y];
Passing Multidimensional Array to a Function. Multidimensional array can be passed in similar way as one-dimensional array. Consider this example to pass two dimensional array to a function: C++ Program to display the elements of two dimensional array by passing it to a function.
If you need a function for 2D array of fixed size, don't pass the sizes. If you need a function that works with 2D arrays of any size, use the proper array passing technique. Your variants strikes me as a weird mix of the two. I don't see the point of doing it that way.
Passing arrays to functions is a bit funny in C and C++. There are no rvalues of array types, so you're actually passing a pointer. To address a 2D array (a real one, not array of arrays), you'll need to pass 2 chunks of data: And these are two separate values, be it C or C++ or with VLA or without or whatnot.
The size of the array is 5. When we call a function by passing an array as the argument, only the name of the array is used. Here, the argument marks represent the memory address of the first element of array marks [5]. However, notice the parameter of the display () function.
Passing arrays to functions is a bit funny in C and C++. There are no rvalues of array types, so you're actually passing a pointer.
To address a 2D array (a real one, not array of arrays), you'll need to pass 2 chunks of data:
And these are two separate values, be it C or C++ or with VLA or without or whatnot.
Simplest, works everywhere but needs more manual work
void foo(int width, int* arr) { arr[x + y*width] = 5; }
VLA, standard C99
void foo(int width, int arr[][width]) { arr[x][y] = 5; }
VLA w/ reversed arguments, forward parameter declaration (GNU C extension)
void foo(int width; int arr[][width], int width) { arr[x][y]=5; }
C++ w/ VLA (GNU C++ extension, terribly ugly)
void foo(int width, int* ptr) { typedef int arrtype[][width]; arrtype& arr = *reinterpret_cast<arrtype*>(ptr); arr[x][y]=5; }
The [x][y] notation with a 2D array works because the array's type contains the width. No VLA = array types must be fixed at compile-time.
Hence: If you can't use VLA, then...
If you can use VLA (C99 or GNU C++ extensions), then...
For C++, boost::multi_array
is a solid choice.
For 2D arrays, you can make two separate allocations:
T
(A)T
(B)Then set the pointers in (A) to point into respective rows of (B).
With this setup, you can just pass (A) around as a simple T**
and it will behave well with [x][y]
indexing.
This solution is nice for 2D, but needs more and more boilerplate for higher dimensions. It's also slower than the VLA solution because of the extra layer of indirection.
You may also run into a similar solution with a separate allocation for every B
's row. In C this looks like a malloc-in-a-loop, and is analogous of C++'s vector-of-vectors. However this takes away the benefit of having the whole array in one block.
There is no clear cut way for doing this but you can use a workaround to treat a 2 dimensional array as a one dimensional array and then reconvert it to a two dimensional array inside the function.
void foo2(int n, int *arr) { int *ptr; // use this as a marker to go to next block int i; int j; for(i = 0; i < n; i++) { ptr = arr + i*n; // this is the starting for arr[i] ... for (j = 0; j < n ;j++) { printf(" %d ", ptr[j]); // This is same as arr[i][j] } } } void bar2() { int arr[10][10]; foo2(10, (int *)arr); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With