yak
yak

Reputation: 3930

Passing multidimensional static array to a function

I need a little advice. Are all those 3 ways of passing static, multidimensional array (here I have 3-dimensional, I guess for 4 dimensions it would be analogical) to a function are correct?

Here's the code:

#include <stdio.h>    
void fun1(int ***tab, int n, int m, int p)
{
   int i,j,k;
   for(i=0; i<n; i++)
   {
      for(j=0; j<m; j++)
      {
        for(k=0; k<p; k++)
        {
           printf("tab[%d][%d][%d] = %d\n", i, j, k, tab[i][j][k]);
        }
        printf("\n");
      }
      printf("\n");
   }
}

void fun2(int tab[2][3][2])
{
    int i,j,k;
    for(i=0; i<2; i++)
    {
       for(j=0; j<3; j++)
       {
          for(k=0; k<2; k++)
          {
             printf("tab[%d][%d][%d] = %d\n", i, j, k, tab[i][j][k]);
          }
          printf("\n");
       }
       printf("\n");
   }
}

void fun3(int tab[][3][2])
{
    int i,j,k;
    for(i=0; i<2; i++)
    {
       for(j=0; j<3; j++)
       {
          for(k=0; k<2; k++)
          {
            printf("tab[%d][%d][%d] = %d\n", i, j, k, tab[i][j][k]);
          }
          printf("\n");
      }
      printf("\n");
  }
}

int main()
{
    int tab[2][3][2] =
    {
        {{0, 1}, {2, 3}, {3, 4}},
        {{5, 6}, {7, 8}, {9, 10}}
    };

    fun1(tab,2,3,2);
    printf("--------------------------\n");
    fun2(tab);
    printf("--------------------------\n");
    fun3(tab);

    return 0;
}

There seem to be a problem with fun1 but can't really understand what does it mean: expected ‘int ***’ but argument is of type ‘int (*)[3][2]’|. Does it mean that only fun2 and fun3 are valid in this case?

Upvotes: 1

Views: 156

Answers (4)

InsertMemeNameHere
InsertMemeNameHere

Reputation: 2433

It is because an int *** points to a pointer to a pointer. int (*)[a][b] a pointer to an int[a][b].

Arrays are laid out flat in memory, meaning something like int[5][5] uses the same amount of space as an int[25]. Making an int[5][5] compatible with an int** would mean row pointers would need to be allocated somewhere.

Upvotes: 1

Venkatesh
Venkatesh

Reputation: 1577

One can use the implementation of fun1 or fun4 to pass multidimensional array to a function.

#include <stdio.h>

void fun1(int n, int m, int p, int tab[n][m][p])
{
int i,j,k;

for(i=0; i<n; i++)
{
    for(j=0; j<m; j++)
    {
        for(k=0; k<p; k++)
        {
            printf("tab[%d][%d][%d] = %d\n", i, j, k, tab[i][j][k]);
        }
        printf("\n");
    }
    printf("\n");
}
}

void fun4(int n, int m, int p, int* tab) {
int i,j,k;
for(i=0; i<n; i++)
{
    for(j=0; j<m; j++)
    {
        for(k=0; k<p; k++)
        {
            printf("tab[%d][%d][%d] = %d\n", i, j, k, tab[i*m*p+j*p+k]);
        }
        printf("\n");
    }
    printf("\n");
}
}

void fun2(int tab[2][3][2])
{
int i,j,k;

for(i=0; i<2; i++)
{
    for(j=0; j<3; j++)
    {
        for(k=0; k<2; k++)
        {
            printf("tab[%d][%d][%d] = %d\n", i, j, k, tab[i][j][k]);
        }
        printf("\n");
    }
    printf("\n");
}
}

void fun3(int tab[][3][2])
{
int i,j,k;

for(i=0; i<2; i++)
{
    for(j=0; j<3; j++)
    {
        for(k=0; k<2; k++)
        {
            printf("tab[%d][%d][%d] = %d\n", i, j, k, tab[i][j][k]);
        }
        printf("\n");
    }
    printf("\n");
}
}

int main()
{
int tab[2][3][2] =
{
    {{0, 1}, {2, 3}, {3, 4}},
    {{5, 6}, {7, 8}, {9, 10}}
};

fun1(2,3,2, tab);
printf("--------------------------\n");
fun4(2,3,2, (int*)tab);
printf("--------------------------\n");
fun2(tab);
printf("--------------------------\n");
fun3(tab);


return 0;
}

Upvotes: 0

John Bode
John Bode

Reputation: 123448

A 3D array expression does not decay to a triple pointer; it decays to a pointer to a 2D array. Given the code

int arr[X][Y][Z];
fun1( arr );

the expression arr in the call to fun1 will decay to type "pointer to Y-element array of Z-element array of int", so the prototype for fun1 needs to be

void fun1( int (*table)[Y][Z] ) // or int table[][Y][Z]
{
  // do something with table[i][j][k]
}

Note that, in this case, Y and Z must be known at compile time.

If you're using a C99 compiler or a C2011 compiler that still supports variable-length arrays, you can do something like the following:

void fun1( size_t x, size_t y, size_t z, (*table)[y][z] ) // or table[][y][z], or table[x][y][z]
{
  // do something with table[i][j][k]
}

int main( void )
{
  int table[2][3][2] = ...;
  fun1( 2, 3, 2, table );
  ...
}

Note that x, y and z must be declared before they can be used in the array parameter declaration.

Upvotes: 2

2501
2501

Reputation: 25752

One is pointer to a pointer to a pointer to an int int ***, and the other is a pointer to an array of dimensions 3 and 2 int (*)[3][2].

Those types are not compatible and their memory layout is not the same. Array is contiguous in memory while pointers to pointers are not.

If you wish to use the first function in a dynamic way where the dimensions are known at runtime then declare it with additional parameters:

void fun1( int n, int m, int p , int a[n][m][p] )...

Upvotes: 2

Related Questions