-1

I have a function that requires an array as the argument and returns the same array after modifying it. The compiling is giving me an error where I pass the argument and call the function. Why is this so?

int solve(int a[9][9])
{
  ...
  return a;

}
int main()
{
  int a[9][9];

  a = solve(a);    <error here>
}

1 Answers1

4

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)

  1. ... 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;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335