49

I am learning C and am having trouble passing the pointer of a 2D array to another function that then prints the 2D array. Any help would be appreciated.

int main( void ){
    char array[50][50];
    int SIZE;

    ...call function to fill array... this part works.

    printarray( array, SIZE );
}

void printarray( char **array, int SIZE ){
    int i;
    int j;

    for( j = 0; j < SIZE; j++ ){
        for( i = 0; i < SIZE; i ++){
            printf( "%c ", array[j][i] );
        }
        printf( "\n" );
    }
}
4
  • 2
    void printarray( char array[][50], int SIZE ) Commented May 23, 2013 at 21:41
  • 2
    While it is possible to do this, you're better off converting it to a 1D array and using j*SIZE+i to index it. Commented May 23, 2013 at 21:42
  • @Dave why? ...............................(just filler) Commented May 23, 2013 at 21:48
  • 2
    @kotlomoy because C's n-D array syntax is ambiguous at best, and indexing it manually forces you to consider the memory order (often useful for caching performance). Also it means you can seamlessly switch to using a dynamic-sized array (via malloc) in the future. Commented May 23, 2013 at 21:55

6 Answers 6

43

char ** doesn't represent a 2D array - it would be an array of pointers to pointers. You need to change the definition of printarray if you want to pass it a 2D array:

void printarray( char (*array)[50], int SIZE )

or equivalently:

void printarray( char array[][50], int SIZE )
Sign up to request clarification or add additional context in comments.

12 Comments

could you explain what the syntax "char *array[50]" means in plain english?
Running cdecl explain 'char (*arr)[50]' yields declare arr as pointer to array 50 of char.
Great answer. char (*array)[50] declares a pointer, with the name array to a 1d array of 50 chars. I thought the explanation in the comment was a little ambiguous and i wanted to improve.
What's the difference between (*array)[50] and *array[50] in the head of a function?
@Jarkid, the former is a pointer to a 50-element array, and the latter is an array of 50 pointers.
|
12

In main(), the variable "array" is declared as

char array[50][50];

This is a 2500 byte piece of data. When main()'s "array" is passed about, it is a pointer to the beginning of that data. It is a pointer to a char expected to be organized in rows of 50.

Yet in function printarray(), you declare

 char **array

"array" here is a pointer to a char *pointer.

@Lucus suggestion of void printarray( char array[][50], int SIZE ) works, except that it is not generic in that your SIZE parameter must be 50.

Idea: defeat (yeech) the type of parameter array in printarray()

void printarray(void *array, int SIZE ){
    int i;
    int j;
    char *charArray = (char *) array;

    for( j = 0; j < SIZE; j++ ){
        for( i = 0; i < SIZE; i ++){
            printf( "%c ", charArray[j*SIZE + i] );
        }
        printf( "\n" );
    }
}

A more elegant solution is to make the "array" in main() an array of pointers.

// Your original printarray()
void printarray(char **array, int SIZE ){
    int i;
    int j;
    for( j = 0; j < SIZE; j++ ){
        for( i = 0; i < SIZE; i ++){
            printf( "%c ", array[j][i] );
        }
        printf( "\n" );
    }
}

// main()
char **array;
int SIZE;
// Initialization of SIZE is not shown, but let's assume SIZE = 50;
// Allocate table
array = (char **) malloc(SIZE * sizeof(char*));
  // Note: cleaner alternative syntax
  // array = malloc(sizeof *array * SIZE);
// Allocate rows
for (int row = 0; row<SIZE; row++) {
  // Note: sizeof(char) is 1. (@Carl Norum)
  // Shown here to help show difference between this malloc() and the above one.
  array[row] = (char *) malloc(SIZE * sizeof(char));
    // Note: cleaner alternative syntax
    // array[row] = malloc(sizeof(**array) * SIZE);
  }
// Initialize each element.
for (int row = 0; row<SIZE; row++) {
  for (int col = 0; col<SIZE; col++) {
    array[row][col] = 'a';  // or whatever value you want
  }
}
// Print it
printarray(array, SIZE);
...

7 Comments

@CarlNorum Just because it is doesn't mean you have to ruthlessly replace it with 1 (or remove it altogether). sizeof statements can go a long way in making your code self-documenting.
@Thomas, if you want to make your code self-documenting, you can do so without being redundant. Use sizeof **array, for example. Then at least if you change the data type later, you get the size adjustment for free.
Array dimensions do not need to be fixed when passing to functions; a function can be declared void printarray(size_t Rows, size_t cols, char array[][cols]), for example. (I have no idea why this is not better known after it has been in the standard for 14 years.)
@Eric Postpischil: Declaring a function with "void printarray(size_t Rows, size_t cols, char array[][cols]);" fails my compiler. Is this a correct test of your suggestion?
@chux: You would need to specify what “my compiler” is before anybody else could really help. It is GCC? Clang? Some Microsoft thing? What was the error message? Some compilers may default to a language version that is old (such as GCC’s c89) or non-standard (such as gnu89). For GCC or clang, try “-std=c99” or “-std=c1x”. For a Microsoft compiler, try GCC or clang. Did you include <stdlib.h> to define size_t? (You can use other integer types for dimensions in the declaration; it can be int instead of size_t.)
|
6

Since C99 supports dynamic-sized arrays, the following style is simply more convenient to pass a 2-dim array:

void printarray( void *array0, int SIZE ){
    char (*array)[SIZE] = array0;
    int i;
    int j;
    for( j = 0; j < SIZE; j++ ){
        for( i = 0; i < SIZE; i ++){
            printf( "%c ", array[j][i] );
        }
        printf( "\n" );
    }
}

2 Comments

This is the answer I like, because it works in the case that you don't know the size at compile time. However, I'd like to make 2 notes: (1.) If you pass both dimension sizes (say, rows and columns), then array should be declared as char (*array)[columns] = array0; (2.) If you use const correctness (in this case you aren't changing any of the values in the array, so it's appropriate), then you'd want to have the array0 param declared as const void *array0, and array declared in the body as char const (*array)[columns] = array0;
An clean alternative without the char (*array)[SIZE] = array0; is printarray(int SIZE, char array[SIZE][SIZE])
2

none of the answers here were what I was looking for, so I'm posting my simple solution to the problem

#include <iostream>

using namespace std;

void example(int* mat, int dim0, int dim1){
    
    for(int i = 0; i < dim0; ++i) {
         for(int j = 0; j < dim1; ++j) {
             auto cur_index = i * dim1 + j;
            cout<< *(mat + cur_index) << endl;
        }
    }
}

int main()
{
    const int dim0 = 3;
    const int dim1 = 2;

    int mat[dim0][dim1];
    
    for(int i = 0; i < dim0; ++i) {
         for(int j = 0; j < dim1; ++j) {
            mat[i][j] = i * dim1 + j;
        }
    }
    
    example(&(mat[0][0]), dim0, dim1);
    return 0;
}

Comments

0

You need to typecast the 2D array to a simple pointer by using (char*)array.

The corresponding dummy argument should just be char *array, rather than char **array. However, you need to know the memory layout to handle the 2D-array correctly. In this case, it should be array[i*SIZE+j] or *(array+i*SIZE+j). The resulting code is:

#include<stdio.h>
void printarray( char *array, int SIZE ){
    for( int j = 0; j < SIZE; j++ ){
        for( int i = 0; i < SIZE; i ++){
            printf( "%c ", array[i*SIZE+j] );
        }
        printf( "\n" );
    }
}


int main(){

  char array[50][50];
    printarray( (char*)array, 50 );
    return 0;
}

Comments

-2

You can easily pass the 2d array using double pointer.

  void printarray( char **array, int n)
  {
     int i, j;
     for(i=0; i<n; i++ )
     {
         for(j=0; j<n; j++)
         {
            printf("%c ", array[i][j] );
         }
        printf( "\n" );
     }
  }

  int main()
  {
      int n = 2;
      int i, j;

      char **array = (char **) malloc(n * sizeof(char*));

      for (i=0; i<n; i++) 
      {
        array[i] = (char *) malloc(n* sizeof(char));
      }

     for (i=0; i<n; i++)
     {
       for (j=0; j<n; j++)
       {
           scanf("%c ", &array[i][j]);
       }
     }

     printarray(array, n);

     return 0;
  }

Full Code : Ideone

1 Comment

There is no arrays in your answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.