I have a function which I want to take, as a parameter, a 2D array of variable size.
So far I have this:
void myFunction(double** myArray){
myArray[x][y] = 5;
etc...
}
And I have declared an array elsewhere in my code:
double anArray[10][10];
However, calling myFunction(anArray)
gives me an error.
I do not want to copy the array when I pass it in. Any changes made in myFunction
should alter the state of anArray
. If I understand correctly, I only want to pass in as an argument a pointer to a 2D array. The function needs to accept arrays of different sizes also. So for example, [10][10]
and [5][5]
. How can I do this?
You can do something like this...
Your output will be as follows...
We can use several ways to pass a 2D array to a function:
Using single pointer we have to typecast the 2D array.
Using double pointer In this way, we also typecast the 2d array
Fixed Size
1. Pass by reference
In C++ passing the array by reference without losing the dimension information is probably the safest, since one needn't worry about the caller passing an incorrect dimension (compiler flags when mismatching). However, this isn't possible with dynamic (freestore) arrays; it works for automatic (usually stack-living) arrays only i.e. the dimensionality should be known at compile time.
2. Pass by pointer
The C equivalent of the previous method is passing the array by pointer. This should not be confused with passing by the array's decayed pointer type (3), which is the common, popular method, albeit less safe than this one but more flexible. Like (1), use this method when all the dimensions of the array is fixed and known at compile-time. Note that when calling the function the array's address should be passed
process_2d_array_pointer(&a)
and not the address of the first element by decayprocess_2d_array_pointer(a)
.Variable Size
These are inherited from C but are less safe, the compiler has no way of checking, guaranteeing that the caller is passing the required dimensions. The function only banks on what the caller passes in as the dimension(s). These are more flexible than the above ones since arrays of different lengths can be passed to them invariably.
It is to be remembered that there's no such thing as passing an array directly to a function in C [while in C++ they can be passed as a reference (1)]; (2) is passing a pointer to the array and not the array itself. Always passing an array as-is becomes a pointer-copy operation which is facilitated by array's nature of decaying into a pointer.
3. Pass by (value) a pointer to the decayed type
Although
int array[][10]
is allowed, I'd not recommend it over the above syntax since the above syntax makes it clear that the identifierarray
is a single pointer to an array of 10 integers, while this syntax looks like it's a 2D array but is the same pointer to an array of 10 integers. Here we know the number of elements in a single row (i.e. the column size, 10 here) but the number of rows is unknown and hence to be passed as an argument. In this case there's some safety since the compiler can flag when a pointer to an array with second dimension not equal to 10 is passed. The first dimension is the varying part and can be omitted. See here for the rationale on why only the first dimension is allowed to be omitted.4. Pass by pointer to a pointer
Again there's an alternative syntax of
int *array[10]
which is the same asint **array
. In this syntax the[10]
is ignored as it decays into a pointer thereby becomingint **array
. Perhaps it is just a cue to the caller that the passed array should have at least 10 columns, even then row count is required. In any case the compiler doesn't flag for any length/size violations (it only checks if the type passed is a pointer to pointer), hence requiring both row and column counts as parameter makes sense here.Note: (4) is the least safest option since it hardly has any type check and the most inconvenient. One cannot legitimately pass a 2D array to this function; C-FAQ condemns the usual workaround of doing
int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10);
as it may potentially lead to undefined behaviour due to array flattening. The right way of passing an array in this method brings us to the inconvenient part i.e. we need an additional (surrogate) array of pointers with each of its element pointing to the respective row of the actual, to-be-passed array; this surrogate is then passed to the function (see below); all this for getting the same job done as the above methods which are more safer, cleaner and perhaps faster.Here's a driver program to test the above functions:
There are three ways to pass a 2D array to a function:
The parameter is a 2D array
The parameter is an array containing pointers
The parameter is a pointer to a pointer
You can use template facility in C++ to do this. I did something like this :
the problem with this approach is that for every value of col which you provide, the a new function definition is instantiated using the template. so,
instantiates the template twice to produce 2 function definitions (one where col = 3 and one where col = 5).
Here is a vector of vectors matrix example
output: