1

UPDATE: A possible duplicate of this question has been reported. While the answers submitted to that question partially solves this one, to explain why we can't use double pointers to represent two dimensional arrays, it does not specify how to access the correct memory address of values which are stored in the pointer; which is the primary theme of this question. The marked answer in this question does an excellent job of clarifying, to anyone confused in the future, about why this is a misunderstood concept and alternative ways on how it can be resolved. This may be useful for future readers who would like to trace the output to understand the concept better!(If you look closely at the comments by the OP in that question, you will realise that the tracing is not clear enough for him to understand. A part of that question present here gives a much better tracing example so that just about anyone can easily understand)

(rest of the question is in its un-edited glory for future readers to reflect upon similar mistake if they happen to make it.)


What I'm trying to do:

  • Trying to see how pointers are used instead of 2D arrays
  • In this case, I'm inserting values to a 2D array(namely, a[ ][ ])
  • I am trying to access the values in that array with a pointer(namely, ptr)
  • I am also trying to trace the memory address from which those values are being taken from
  • Trying to know where I'm going wrong? (would appreciate an appropriate explanation and if possible, a link to reference and learn further)

What I've tried:
Below is a sample code:

int main()
{
  int a[2][2]={{5,7},
               {0,1}};
  int** ptr=(int**)a;
  int i,j;
for(i=0;i<2;i++){
    for(j=0;j<2;j++){
        printf("%d printing from==>%x\n",&ptr[i][j],((&ptr[i])+j));
   }
  }
  getch();
  return(0);
}

In the above code, I'm trying to print the values present inside matrix a[ ][ ] with the help of pointer ptr. In doing so, I am tracing the address from where(in the memory address) the printing actually takes place. I seem to have encountered a disastrous output in the form of:

5 printing from ==>12ff7c
9 printing from ==>12ff80
7 printing from ==>12ff80
11 printing from ==>12ff84

Then I modified the line:

printf("%d printing from==>%x\n",&ptr[i][j],((&ptr[i])+j));

with this:

printf("%d printing from==>%d\n",&ptr[i][j],*((&ptr[i])+j));

to know which values were actually present in those addresses:

5 printing from ==>5
9 printing from ==>7
7 printing from ==>7
11 printing from ==>0

My take on this is that: &ptr[i][j] is equivalent to (*(&ptr[i])+j)) and ((&ptr[i])+j)) doesn't really tell me the addresses of even those numbers because &ptr[i] defines an address which is incremented by j in this case(but since j is reset to 0 in each outer loop iteration; that will cause same memory address to be pointed twice) Am I wrong with this chain of thought?

How can you help me?

  • Here is my code failing miserably, and based upon the article on Double Pointer and Two Dimensional Arrays in C that I read here. Have I fundamentally misunderstood it?
  • Could you post a correct cpp code by modifying my given code here and posting your own perma-link in the comments?(You can do that by clicking the "GET URL" button below the coding area in that site)
  • I would highly appreciate an answer based on C instead of C++ where typedef ans such is possible I am trying to learn pointers better
Community
  • 1
  • 1
Siddhant Rimal
  • 975
  • 2
  • 11
  • 32
  • 1
    You are compiling C++ (and including C++ headers). If you really want to learn C then compile C (the languages are *very* different in many ways). – crashmstr Mar 30 '16 at 11:50
  • 1
    Use `%p` instead of `%x` for printing pointer values. Using `%x` is undefined behaviour on many platforms. – Jabberwocky Mar 30 '16 at 11:53
  • 1
    Why don't you print and analyze `printf("%d printing from==>%p\n",a[i][j],(void *)&a[i][j]);`? – Mohit Jain Mar 30 '16 at 11:53
  • `arr[i]` is the same as `(*((arr)+(i)))`. `arr[i][j]` is the same as `(*(*((arr)+(i)))+(j))`. – Ian Abbott Mar 30 '16 at 11:55
  • 2
    Did you even read the article you link to? The code you show comes from a section that says it does not work! *"It happens because two dimensional array matrix and double pointer pmat are different types and using them in similar fashion points to different locations in memory."* – crashmstr Mar 30 '16 at 11:58
  • Your array and pointer declarations are incompatible. An `int **ptr` pointer can never be used to access an `int a[2][2]` array. The compiler would have told you this if you hadn't suppressed the error message with a cast. Tip: Do *not* use casts for this sort of pointer assignment. If a cast is needed, it's most likely masking a bug. – Tom Karzes Mar 30 '16 at 12:04
  • Your `ptr` is of type `int **`. Your `a` is an array of type `int [2][2]`. In most expressions, `a` will decay to a pointer of type `int (*)[2]`. That is not the same type as your `ptr`. – Ian Abbott Mar 30 '16 at 12:04
  • Possible duplicate of [Why can't we use double pointer to represent two dimensional arrays?](http://stackoverflow.com/questions/4470950/why-cant-we-use-double-pointer-to-represent-two-dimensional-arrays) – Klas Lindbäck Mar 30 '16 at 12:12
  • @KlasLindbäck , +1 for that link. I wonder why I never found it. Maybe incorrect keywords. Answers some of my questions so you are partially correct. This is a possible **partial** duplicate of that question. – Siddhant Rimal Apr 02 '16 at 13:24
  • @lancel0t Is there a good canonical answer describing the difference between double pointer and multidimensional arrays? Cause it is very common that people don't know the difference. – Klas Lindbäck Apr 04 '16 at 07:01

1 Answers1

5

A 2D array and a pointer to pointer are different animals!

A 2D array, say int arr[N][M], is an array of N*M consecutive elements with the following relation &arr[i][j] == &arr[0][0] + i * M + j.

A pointer of pointers is a pointer to an array of pointers, each pointing to another array.

So what can you do?

  • process the array as a 1D array with explicit indexing

    int main()
    {
      int a[2][2]={{5,7},
                   {0,1}};
      int* ptr=a[0];  // a[0] decays to a pointer...
      int i,j;
      for(i=0;i<2;i++){
        for(j=0;j<2;j++){
            printf("%d printing from==>%x\n",ptr[j + 2 *i],ptr + j + 2 * i);
        }
      }
      //getch();
      return(0);
    }
    
  • explicitely creates an array of pointers

    int main()
    {
      int a[2][2]={{5,7},
                   {0,1}};
      int *b[] = { a[0], a[1] };  // array of pointers pointing to beginning or rows
      int** ptr=b;  // b decays to a pointer to pointer
      int i,j;
      for(i=0;i<2;i++){
        for(j=0;j<2;j++){
            printf("%d printing from==>%x\n",ptr[i][j],&(ptr[i][j]));
        }
      }
      //getch();
      return(0);
    }
    
  • explictely use a pointer to array of definite size:

    int main()
    {
      int a[2][2]={{5,7},
                   {0,1}};
      int (*ptr)[2] = a;  // a decays to a pointer arrays of size 2
      int i,j;
      for(i=0;i<2;i++){
        for(j=0;j<2;j++){
            printf("%d printing from==>%x\n",ptr[i][j],&(ptr[i][j]));
        }
      }
      //getch();
      return(0);
    }
    

Also note that I have no explicit cast in above code to let the compiler control that the inderection levels are correct.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Could you recommend me some reading materials or online tutorials/courses to zip through this quickly. I seem to have developed a LOT of misconceptions and incorrect information on C programming concepts. I would like to know a nice place to start. Thanks for this detailed explaination btw. Was really helpful. I want to learn about all the basic must-know things like the relation &arr[i][j] == &arr[0][0] + i * M + j that you wrote over there. – Siddhant Rimal Mar 30 '16 at 13:39