For starters arrays do not have the assignment operator. Array designators are non-modifiable lvalues.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
- ... A modifiable lvalue is an lvalue that does not have array type,
does not have an incomplete type, does not have a const
qualified type, and if it is a structure or union, does not have any
member (including, recursively, any member or element of all contained
aggregates or unions) with a const qualified type.
Secondly parameters declared like arrays are adjusted to pointers to their element types.
From the C Standard (6.7.6.3 Function declarators (including prototypes))
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to type’’, where the type qualifiers (if any)
are those specified within the [ and ] of the array type derivation...
For example this function declaration
void f(int a[9][9]);
is adjusted to
void f(int ( *a )[9]);
Thirdly functions may not have arrays as the return type. But they may return pointers.
From the C Standard (6.9.1 Function definitions)
3 The return type of a function shall be void or a complete object
type other than array type.
So for example the function solve
can be declared like
int ( * solve(int a[9][9]) )[9]
{
// ...
return a;
}
And if the function changes elements of the array in any case it does not make sense to write
int a[9][9];
a = solve(a);
You can just write
int a[9][9];
solve(a);
or
int a[9][9];
int ( *p )[9] = solve(a);
Here is a demonstrative program
#include <stdio.h>
#define M 2
#define N 3
int ( * f( int ( *a )[N], size_t n ) )[N]
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ ) a[i][j] *= 10;
}
return a;
}
int main(void)
{
int a[M][N] =
{
{ 1, 2, 3 },
{ 4, 5, 6 }
};
f( a, M );
for ( size_t i = 0; i < M; i++ )
{
for ( size_t j = 0; j < N; j++ ) printf( "%d ", a[i][j] );
putchar( '\n' );
}
putchar( '\n' );
int ( *p )[N] = f( a, M );
for ( size_t i = 0; i < M; i++ )
{
for ( size_t j = 0; j < N; j++ ) printf( "%d ", p[i][j] );
putchar( '\n' );
}
putchar( '\n' );
f( p, M );
for ( size_t i = 0; i < M; i++ )
{
for ( size_t j = 0; j < N; j++ ) printf( "%d ", p[i][j] );
putchar( '\n' );
}
putchar( '\n' );
return 0;
}
Its output is
10 20 30
40 50 60
100 200 300
400 500 600
1000 2000 3000
4000 5000 6000
To simplify the function declaration you could introduce a typedef name.
For example
typedef int( *PArray )[N];
PArray f( int ( *a )[N], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ ) a[i][j] *= 10;
}
return a;
}
Or even like this
typedef int( *PArray )[N];
PArray f( PArray a, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ ) a[i][j] *= 10;
}
return a;
}