understanding double pointers in C

Discussion in 'Mac Programming' started by NRose8989, May 13, 2009.

  1. NRose8989 macrumors 6502a

    Joined:
    Feb 6, 2008
    #1
    I having a lot of trouble trying to figure out this problem. Take a look at this function.

    Code:
    void function3(int **twod)
    {
    	printf("twod is: %p\n", twod); // this prints the location of twod
    	printf("*twod + 1 is: %p\n", *twod + 1); 	
    }

    this function will be passed a 2D array of ints but I really can't figure out what is happening because the first line prints out 0xbffffa54 but the next line will print out 0x6, which is the value at twod[0][2].

    Here is the array as it is declared in main:

    Code:
    int twod[4][3] = {{2,4,6}, {8,10,12}, {14, 16, 18}, {20, 22, 24}};
    Can someone please explain to me what is going to with *twod + 1? because naturally I would think that it first dereferenced twod then adds 1 to where it points to..... but now I'm really confused. thanks
     
  2. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    Unless you did a little doing to twod in main, things aren't going to go well passing it to function3. Here's the code I wrote to do something similar to this two different ways:
    Code:
    #include <stdio.h>
    
    void function3(int **);
    void function4(int twod[][3]);
    
    int main(int argc, char *argv[]) {
      int twod[4][3] = {{2,4,6}, {8,10,12}, {14, 16, 18}, {20, 22, 24}};
      int *twodPass[4];
      twodPass[0]=twod[0];
      twodPass[1]=twod[1];
      twodPass[2]=twod[2];
      twodPass[3]=twod[3];
      function3(twodPass);
      function4(twod);
      return 0;
    }
    
    void function3(int **twod) {
            printf("twod is: %p\n", twod); // this prints the location of twod
            printf("*twod + 1 is: %p\n", *twod + 1); 
    }
    
    void function4(int twod[][3]) {
            printf("twod is: %p\n", twod); // this prints the location of twod
            printf("*twod + 1 is: %p\n", *twod + 1); 
    }
    
    
    Output:
    twod is: 0xbffffc80
    *twod + 1 is: 0xbffffc94
    twod is: 0xbffffc90
    *twod + 1 is: 0xbffffc94

    An int ** is different from an int[x][y]. One is a pointer to a pointer, or perhaps a pointer to an array of pointers. The other is x*y*sizeof(int) bytes that you can access conveniently with two indexes. In the example i set up an int *[] to allow for function3 to operate properly. You didn't post all of your code, but i think it would be fair to guess that there was a warning. EDIT: I'm a bit tired, and should be sleeping. Gruffalo's explanation of why you got 0x6 is correct. You can test by modifying the first value of twod.

    -Lee
     
  3. Gruffalo macrumors newbie

    Gruffalo

    Joined:
    Jan 27, 2006
    #3
    It is probably easier to first point out that the declaration of the 2D array is just a convenience. In memory, you get from exactly the same as you would get if you declared:

    Code:
    int oned[12] = {2,4,6,8,10.....};
    
    So, your function3 is expecting an array of pointers to integers. When you dereference that you are saying 'what is the value' of the first pointer in the array, and the first 'pointer', has the value or address 0x2. Now if you increment an integer pointer by 1, you are adding 4 (4 bytes in an integer) which gives you the answer 0x6.
     
  4. NRose8989 thread starter macrumors 6502a

    Joined:
    Feb 6, 2008
    #4
    OK now that makes sense to me. thanks.
     
  5. rrpalma macrumors member

    Joined:
    Sep 21, 2008
    #5
    to the OP, please realize that assuming p is a pointer to an int,
    *p + 1
    adds 1 to the value pointed by p
    whereas *(p+1)
    dereferences the integer right next to the one pointed by p (which is probably what you wanted)

    Perhaps the following quick C++ code might help a little (or further confuse you):

    Code:
    #include <iostream>
    using namespace std;
    
    void f1(int (*p)[3]);
    void f2(int *q);
    
    int main() {
    
    	int myArray[4][3] = { { 2, 4, 6 }, { 8, 10, 12 }, { 14, 16, 18 }, { 20,
    			22, 24 } };
    	cout << "Program starting" << endl;
    	f1(myArray);
    	f2(myArray[0]);
    	return 0;
    }
    
    void f1(int (*p)[3]) {
    	cout << "pointer p is " << p << endl;
    	cout << "item pointed to by p is " << **p << endl;
    	cout << "item pointed to by p + 2 is " << **(p+2) << endl;
    	return;
    }
    
    void f2(int *q) {
    	cout << "pointer q is " << q << endl;
    	cout << "item pointed to by q is " << *q << endl;
    	cout << "item pointed to by q + 2 is " << *(q+2) << endl;
    	return;
    }
    
    the above code produces the following output on Eclipse Ganymede, Linux 64 bit, with CDT:

    Code:
    Program starting
    pointer p is 0x7fff19d23820
    item pointed to by p is 2
    item pointed to by p + 2 is 14
    pointer q is 0x7fff19d23820
    item pointed to by q is 2
    item pointed to by q + 2 is 6
    
     

Share This Page