First, given the variable-length array
int array[m][n];
your void make_arr( int array[m][n] )
won't work with int **array
because int **array
is not an actual 2-dimensional array. int **array
is a pointer to an array of pointers to multiple and completely separate one-dimensional arrays. Such a construct is simply incompatible with being treated as an actual array.
And you can't give int array[m][n];
global scope because it's variable-length, and global variables are static (unchanging, not necessarily C's static
) and have to be fixed-size.
And you can't use something like a typedef
to create an "array type", because that's a compile-time definition and the array is "sized" at run time.
So you need to allocate the array dynamically, but the global variable use to access the array won't have sizing information associated with it.
The global variable pretty much has to be a void *
.
To access the array, you have to create a pointer at run-time to a VLA and assign the global void *
to that pointer.
This would work (note that the local pointer has to be dereferenced to access the array):
#include <stdlib.h>
void *array;
int m;
int n;
// create the array, assumes both
// m and n are already set
void createArray()
{
int ( *localArrayPtr )[m][n] = malloc( sizeof( *localArrayPtr ) );
array = localArrayPtr;
}
void fillArray( void )
{
int ( *localArrayPtr )[m][n] = array;
for ( int ii = 0; ii < m; ii++ )
{
for ( int jj = 0; jj < n; jj++ )
{
( *localArrayPtr )[ ii ][ jj ] = rand();
}
}
}
void someOtherFunc( void )
{
int ( *localArrayPtr )[m][n] = array;
( *localArrayPtr )[ x ][ y ] = ...;
}
As an exercise, it works. Forcing a VLA to have global scope, though, causes accessing the array to be more complex than necessary, adding to existing problems with using globally-scoped variables.
It's probably a lot better from both a scope and code complexity perspective to just pass the array to functions via arguments, such as void someFunc( int m, int n, int array[ m ][ n ] ) { ... }
. Accessing elements would then just be in the form array[ x ][ y ]
.
You could create "getter" and "setter" functions to hide the complexity:
int getElement( int x, int y )
{
int ( *localArrayPtr )[m][n] = array;
return( ( *localArrayPtr )[ x ][ y ] );
}
void setElement( int x, int y, int value )
{
int ( *localArrayPtr )[m][n] = array;
( *localArrayPtr )[ x ][ y ] = value;
}
A good optimizing compiler would likely inline those.