Reputation: 39
I'm trying to make 2D array struct in C like this in main function.
function_1(struct example** ex){}
void main(){
struct example ex[num_1][num_2];
function(ex);
}
But gcc keep telling me that type of ex and struct example** ex is different. How can I solve this error?
Upvotes: 0
Views: 112
Reputation: 123468
A 2D array expression doesn’t decay to a pointer to pointer, it decays to a pointer to an array.
Unless it is the operand of the sizeof
, _Alignof
, or unary &
operators, or is a string literal used initialize a character array in a declaration, an expression of type "N-element array of T
" will be converted, or "decay", to an expression of type "pointer to T
" and the value of the expression will be the address of the first element of the array.
In the call to function
, the expression ex
decays from type "num_1
-element array of num_2
-element array of struct example
" to "pointer to num_2
-element array of struct example
", so your function prototype needs to be
void function( struct example (*ex)[num_2] )
{
...
ex[i][j] = some_value();
...
}
In the context of a function parameter declaration, T a[N]
and T a[]
are "adjusted" to T *a
, so you could also write that prototype as
void function( struct example ex[][num_2] )
{
...
ex[i][j] = some_value();
...
}
There are a couple of problems with this - function
doesn’t know how many rows are in the array, so you would need to pass that as a separate parameter:
void function( struct example (*ex)[num_2], size_t rows )
{
...
}
Also the function can only accept arrays with num_2
columns - it cannot work on any arbitrarily-sized 2D array.
If your function needs to handle arbitrarily-sized arrays and you have a compiler that supports variable-length arrays, you can do something like this:
void function( size_t rows, size_t cols, struct example ex[rows][cols] )
{
...
}
and call it from main
as
function( num_1, num_2, ex );
If your compiler doesn’t support VLAs, you’ll have to get creative. One trick is to pass a pointer to the first element and treat it as a 1D array in the function:
void function( struct example *ex, size_t rows, size_t cols )
{
...
ex[i * rows + j] = some_value();
...
}
and call it as
function( &ex[0][0], num_1, num_2 );
Note that this trick only works for 2D arrays defined as
T a[M][N];
or arrays dynamically allocated as
T (*p)[N] = malloc( sizeof *p, M );
It won’t work for 2D arrays allocated as
T **p = malloc( sizeof *p * M );
for ( size_t i = 0; i < N; i++ )
p[i] = malloc( sizeof *p[i], N );
but in that case, your function prototype would be
void function( T **p, size_t rows, size_t cols )
{
...
}
As a final note, main
returns int
, not void
. Older compilers won’t complain, but the behavior is undefined and could cause problems at runtime.
Upvotes: 0
Reputation: 635
I edited my original answer:
You could instead write
function_1(struct example (*pex) [num_1][num_2]){}
void main(){
struct example ex[num_1][num_2];
function(& ex);
}
at least if you know num_1
and num_2
at compile time.
Upvotes: 1