3

I am trying to learn about double pointers.I am trying to print a 2d array by passing the address of the array to a function.But compilation error is coming.I am unable to understand why ??

Below is the code.

#include<stdio.h>
#include<stdlib.h>
void print(int **,int,int);
int main()
{

    int i,j;
    int a[][3]={
                {1,0,1},{1,1,1},   {1,1,1}
            };
            print(a,3,3);
            return 0;
}
void print(int **A, int n11, int n12)
{
    int i,j;
   for(i=0;i<3;i++)
            {
                for(j=0;j<3;j++)
                {
                    printf("%d  ",*((A+i*n12)+j);
                }
                printf("\n");
            }
}

Error log---

set_matrix.c: In function 'main':
set_matrix.c:29:19: warning: passing argument 1 of 'print' from incompatible poi
nter type [-Wincompatible-pointer-types]
             print(a,3,3);
                   ^
set_matrix.c:9:6: note: expected 'int **' but argument is of type 'int (*)[3]'
 void print(int **,int,int);
  ^
asad_hussain
  • 1,959
  • 1
  • 17
  • 27
  • 2
    Take a look also at [this SO post](http://stackoverflow.com/questions/7586702/is-2d-array-a-double-pointer) – LPs May 26 '16 at 12:30
  • 2
    You're also missing a closing bracket for the printf –  May 26 '16 at 12:58
  • @LPs . This is a better duplicate iof [\[ this \]](http://stackoverflow.com/questions/1052818/create-a-pointer-to-two-dimensional-array) question. – sjsam May 26 '16 at 14:27

2 Answers2

1

When I test your code, I get these errors and warnings.

/home/dac/ClionProjects/gnu/main.c: In function ‘main’:
/home/dac/ClionProjects/gnu/main.c:11:9: warning: passing argument 1 of ‘print’ from incompatible pointer type [-Wincompatible-pointer-types]
   print(a,3,3);
         ^
/home/dac/ClionProjects/gnu/main.c:3:6: note: expected ‘int **’ but argument is of type ‘int (*)[3]’
 void print(int **,int,int);
      ^
/home/dac/ClionProjects/gnu/main.c: In function ‘print’:
/home/dac/ClionProjects/gnu/main.c:21:35: error: expected ‘)’ before ‘;’ token
       printf("%d  ",*((A+i*n12)+j);
                                   ^
/home/dac/ClionProjects/gnu/main.c:21:14: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
       printf("%d  ",*((A+i*n12)+j);
              ^
/home/dac/ClionProjects/gnu/main.c:22:5: error: expected ‘;’ before ‘}’ token
     }
 ^

If you just want to print a matrix, you can use the matrix you created and redeclare how you print it, similar to the following code.

#include <stdio.h>
#define size 3
void print_matrix(int x, int y, int a[size][size]) {

  int i, j;
  for(i = 0; i < x; i++) {
    for(j = 0; j < y; j++)
      printf("%d\t", a[i][j]);
    putchar('\n');
  }
}

int main()  {
  int a[size][size]={
          {1,0,1},{1,1,1},   {1,1,1}
  };
  print_matrix(size,size, a);
  return 0;
}

Output

/system/cmake/generated/gnu-fadf49ce/fadf49ce/Debug/gnu
1   0   1   
1   1   1   
1   1   1   

Process finished with exit code 0

If you want to learn about double-pointers, try using and manipulating the argv of your program - it is already a double-pointer. Or create new matrices dynamically: int **matrix = malloc(size * sizeof(int *));

Or if you want to use the pointer version of your original problem (printing a matrix using pointers).

#include <stdio.h>
#define size 3

void print_matrix(int (*a)[size], int n) {
  int i, j;
  for(i = 0; i < n; i++) {
    for(j = 0; j < n; j++)
      printf("%d\t", a[i][j]);
    putchar('\n');
  }

}
int main()  {
  int a[][size]={
          {1,0,1},{1,1,1},   {1,1,1}
  };
  print_matrix(a, size);
  return 0;
}

The above code uses pointers and prints the same matrix:

1   0   1   
1   1   1   
1   1   1   

To learn pointers, you can declare a matrix of pointers and try to manipulate it, the following creates and prints a matrix of random numbers using pointers.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define size 3

void print_matrix(int ***matrix) {
  for (unsigned row = 0; row < size; row++) {
    for (unsigned column = 0; column < size; column++) {
      printf("%d ", matrix[row][column]);
    }
    printf("\n");
  }
}

int main() {
  int ***matrix = malloc(size * sizeof(int **));
  if (!matrix) abort();
  srand(time(NULL));
  for (unsigned row = 0; row < size; row++) {
    matrix[row] = calloc(size, sizeof(int *));
    if (!matrix[row]) abort();
    for (unsigned column = 0; column < size; column++) {
      matrix[row][column] = rand();
    }
  }
  print_matrix(matrix);
  return 0;
}

Output

2058554958 959327445 396140031 
214331704 706399125 124749117 
1280566165 206604059 668072276 
Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424
  • ,Thaks,but i need some more help.Ur declaration of `int (*a)[size]` means that `a is an array of "size" number of integers`.Am i right ?correct me if i'm wrong. – asad_hussain May 26 '16 at 15:43
1

I am trying to learn about double pointers

I am not sure the terminology is correct, but I wouldn't refer a pointer to pointer as a double pointer because you can easily get confused with a double* & **.

Consider int x=1.0. You can have :

int *ptr=&x; // You make ptr point to x(ie x's memory address).

But remember that pointer is also a type - to be precise an object. An object occupies memory. To store the address of ptr (ie &ptr), you need a pointer to a pointer so :

int **ptr_to_ptr=&ptr; // says ptr_to_ptr is a pointer to an (int*)

The bigger problem here is how can we declare a pointer to int a[][].

For an array say, int a[3], the pointer that should represents it should be of following format - int (*p)[3]. We say p is a pointer to an array of 3 integers.

Here the difference is that you're having an array of arrays ie int a[][3]. The pointer to this array should of the this format - int (*p)[][3]. We say p is pointer to array, each element of this array itself is an array of 3 integers.

Now comparing int a[3] and int a[3][3]

        int a[3]                    |           int a[3][3]
________________________________________________________________________
      &a[0] ~ a (1)                 |   &a[0][0] ~ &a[0] ~ a
                                    |               |------> follows (1)
                                    |              
     a[0] is an int                 |        a[0] is an int[3]
                                    |
                                    |
 you pass '&a' to int(*)[]          |     you pass '&a' to int(*)[][]
 (You omit the &, you get-but the   |   (You omit the &, you get-but the 
 argument is of type int * error)   |argument is of type int (*)[3] error)
                                    |
________________________________________________________________________

So the right way to implement your programme is :

#include<stdio.h>
#include<stdlib.h>
void print(int (*)[][3],int); //You need to pass only the  rows
int main()
{
  int i,j;
  int a[][3]={
    {1,0,1},{1,1,1},{1,1,1}
  };
  print(&a,3); // You can programmtically determine the number of rows
  return 0;
}
void print(int (*A)[][3], int x) // You cannot have int (*A)[][]
{
  int i,j;
  for(i=0;i<3;i++)
  {
    for(j=0;j<3;j++)
    {
      printf("%d\t",(*A)[i][j]);
    }
    printf("\n");
  }
}
sjsam
  • 21,411
  • 5
  • 55
  • 102
  • sjsam,Thanks for ur help. But when i declare an array(1d) of integers as `int (*p)[3]` and try to print ,it doesn't executes.i request u to explain. – asad_hussain May 26 '16 at 15:06
  • @a874: declare? If you just do int (*ptr)[3]; as in a statement, then ptr is cant be used unless it is made to point to an array say int a[3] or you explicitly allocate some memory for it using malloc – sjsam May 26 '16 at 15:39