Thread: Pointer to a Pointer clarification

  1. #1
    Registered User Tommo's Avatar
    Join Date
    Jun 2007
    Location
    Scotland
    Posts
    101

    Pointer to a Pointer clarification

    Hi guys. I'm looking at a 'pointers to pointers' tutorial here.

    Code:
    int **ipp;
    int i = 5, j = 6; k = 7;
    int *ip1 = &i, *ip2 = &j;
    
    ipp = &ip1;
    Code:
    Is (ipp = &ip1) == (**ipp = &i ) ?
    Last edited by Tommo; 08-19-2007 at 01:07 PM.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Short answer to your direct question: No, but **ipp points to the value of i.

    Theoretically it would be equal to
    Code:
    ipp = &&i;
    But there's no such thing as "&&" operand (for taking the address of an address).

    The variable ipp is a pointer that holds the address of another pointer. That second pointer holds the address of i.

    If you think of memory as a set of safetyboxes in a bank-vault: Each one has a number. A pointer is essentially a safetybox that contains the number of a different safetybox. So if we give these a number:
    i is safetybox 123, and in it is 5.
    ip is safetybox number 333, in it is the number 123
    ipp is safetybox 400, and it contains 333.

    &i is the number of the safetybox containing i. Of course, if we change the value of i, we change the value 5 that is in box 123. The safetybox is still 123.

    Does this make some sense to you.

    --
    Mats

  3. #3
    Registered User Tommo's Avatar
    Join Date
    Jun 2007
    Location
    Scotland
    Posts
    101
    This does indeed make sense, yes. Thank you very much.

    So I can only declare a pointer to a pointer if such a pointer already exists - I cannot just let it equal some variable.

    i.e i cant just do this:
    Code:
    int i = 5, **pp;
    pp = &i;
    has to be:
    Code:
    int i=5, **pp;
    int *p = &i;
    pp = &p;
    Also, why isn't it 'int **pp = &p' ? I would've thought this following on from 'int *p = &i'

    I honestly do understand the analogy of the safetyboxes, but the specifics are still tripping me up.

    Please correct me if I'm wrong but you cannot do this:
    Code:
    void function( int **pp );
    main() {
      int i;
      function( &i );
    }
    It should be this:
    Code:
    void function( int **pp );
    main() {
    int i;
    int *p = &i;
    function( &p );
    }
    Is this correct?
    Last edited by Tommo; 08-19-2007 at 01:10 PM.

  4. #4
    Registered User Tommo's Avatar
    Join Date
    Jun 2007
    Location
    Scotland
    Posts
    101
    OK, I tried to write a little test program.
    Code:
    #include <stdio.h>
    
    void myim( int ** );
    
    int main(void) {
    
            int i, *p;
            i = 5;
            p = &i;
            printf("i is %d, p is %d\n",i, *p);
            myim( &p );
            printf("i is %d, p is %d\n", i, *p);
            return 0;
    }
    
    void myim( int **pp ) {
            *pp += 1;
    }
    Output:
    i is 5, p is 5
    i is 5, p is -1077564144

    I was expecting:
    i is 5, p is 5
    i is 6, p is 6

    What went wrong?

  5. #5
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Code:
    void myim( int **pp ) {
            *pp += 1;
    }
    this does pointer arithmetics. it changes where the pointer pointed to by pp points to -> effectively changes where p in main points to and that is not i anymore. it's the int that follows i in memory.
    Kurt

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    835
    If you want to increment what p points to, the function should look like
    Code:
    void myim(int *p) {
      *p += 1; // or (*p)++; or ++*p;
    }

  7. #7
    Registered User Tommo's Avatar
    Join Date
    Jun 2007
    Location
    Scotland
    Posts
    101
    OK, then why are chars an exception to the rule:
    Code:
    #include <stdio.h>
    
    void get_string(char **s)
    {
        *s = "this is just annoying";
    }
    int main(void)
    {
        char *s;
        get_string(&s);
        printf("s is \"%s\"\n", s);
        return 0;
    }
    prints 's is "this is just annoying"'.

    Now:
    Code:
    #include <stdio.h>
    
    void myim( int **pp ) {
            *pp = 7;
    }
    
    int main(void) {
    
            int *p;
            myim( &p );
            printf("p is %d\n", *p);
            return 0;
    }
    Compilation error. Now I know this is because p isn't pointing to anything, but with the same code for a char type, this rule doesn't seem to apply.

    @robatino: i would have to pass '&i' in that case. The whole point to this is to use pointers to pointers.

    @ZuK: I thought that was the case, thanks for clarifying. Out of curiosity, is there any way to change p and i? Do i have to change i first in order for p to change? In that case, what I was attempting was impossible?

    Thanks for your help guys.

  8. #8
    Chinese pâté foxman's Avatar
    Join Date
    Jul 2007
    Location
    Canada
    Posts
    404
    OK, then why are chars an exception to the rule:
    Code:
    #include <stdio.h>
    
    void get_string(char **s)
    {
        *s = "this is just annoying";
    }
    int main(void)
    {
        char *s;
        get_string(&s);
        printf("s is \"&#37;s\"\n", s);
        return 0;
    }
    In fact, this is due to how string are represented. Look at this little example

    Code:
    #include <stdio.h>
    
    char *string = "this is just annoying";
    
    void get_string(char **s)
    {
        *s = string;   //  *(char **) = (char *)
    }
    int main(void)
    {
        char *s;
        get_string(&s);
        printf("s is \"%s\"\n", s);
        return 0;
    }

    And for your other example, you shouldn't get an error, you should only get a warning (in the case warning aren't shown as errors heh).
    Now I know this is because p isn't pointing to anything, but with the same code for a char type, this rule doesn't seem to apply.
    In fact, this is because int * differs in level of indirection from int, not because p isn't pointing to anything. Because you could write something like this
    Code:
    #include <stdio.h>
    
    void myim( int **pp ) {
            *pp = (int *) 7;
    }
    
    int main(void) {
    
            int *p;
            myim( &p );
            printf("p is %d\n", *p);
            return 0;
    }
    and get garbage value at the output (if the program execute correctly, which might not happen, you would get the value of a int starting at adress 7) but you shouldn't get a compilation error.
    Last edited by foxman; 08-19-2007 at 03:49 PM.

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    835
    It might clarify things a bit if you wrote
    Code:
      printf("*p is &#37;d\n", *p);
    since you're printing *p, not p. On the other hand, myim(&p) is changing the value of p, not *p.

  10. #10
    Registered User
    Join Date
    Jun 2007
    Posts
    19
    I apologize about bringing up an older thread; but I would like to add to it, rather then create a new thread.

    I understand the "theory" behind pointers to pointers. However, I am having a hard time with the application of this topic. Besides using a function to return the pointer value, where else might I use pointers to pointers?

    Thanks,


    KiaiViper

  11. #11
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Code:
    int main (int argc, char ** argv) ?
    ;-)

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by kiai_viper View Post
    I apologize about bringing up an older thread; but I would like to add to it, rather then create a new thread.

    I understand the "theory" behind pointers to pointers. However, I am having a hard time with the application of this topic. Besides using a function to return the pointer value, where else might I use pointers to pointers?

    Thanks,


    KiaiViper
    That would definitely be the most common scenario. Walking through pointer arrays is another
    Code:
    int *arr[20];
    int **pp;
    int i;
    pp = arr;
    for(i = 0; i < 20; i++) {
       if (**pp = 7) {   // is the pointer at this place in array pointing to 7?
           printf("Found a seven\n");
       }
       pp++;
    }
    --
    Mats

  13. #13
    Registered User
    Join Date
    Feb 2006
    Posts
    54
    Dynamically allocated 2d arrays: i.e.
    Code:
    #include <stdio.h>
    #define WIDTH 20
    #define HEIGHT 20
    
    
    int main(int argc, char** argv) {
      int** arr;
      int i, k, z=0;
      arr = malloc(HEIGHT*sizeof(int*));
      for (i=0;i<HEIGHT;i++) {
        arr[i] = malloc(WIDTH*sizeof(int));
        for (k=0;k<WIDTH;k++) {
          arr[i][k] = z++;
        }
      }
      return 0;
    }

  14. #14
    Registered User
    Join Date
    Jun 2007
    Posts
    19
    Thanks for the responses. That was the clarification that I needed.


    --KiaiViper

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 0
    Last Post: 03-20-2008, 07:59 AM
  2. What is a virtual function pointer?
    By ting in forum C++ Programming
    Replies: 4
    Last Post: 03-05-2008, 02:36 AM
  3. scope of a pointer?
    By Syneris in forum C++ Programming
    Replies: 6
    Last Post: 12-29-2005, 09:40 PM
  4. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  5. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM