简体   繁体   中英

Pointer to pointer argument variable and how they work? e.g. function(int **ptr)

I am writing code to learn what happens when pointers are passed as arguments in a function.

void ptrTest(int **arg_ptr); 

int main() {
    int some_var = 5;
    int *ptr1;
    ptr1 = &some_var;

    printf("Address of some_var: %u\n\n", &some_var);
    printf("Value stored in *ptr1 (references to some_var): %u\n", ptr1);
    printf("Address of *ptr1 variable: %u\n\n", &ptr1);
    ptrTest(ptr1);
}

void ptrTest(int **arg_ptr){
    printf("Value stored in **arg_ptr (references to some_var): %u\n",arg_ptr);    
}

The result is as follows:

Address of some_var: 3119323004

Value stored in *ptr1 (references to some_var): 3119323004
Address of *ptr1 variable: 3119322992

Value stored in **arg_ptr (references to some_var): 3119323004

I am surprised that arg_ptr takes the value that references to address of some_var. I was expecting **arg_ptr to point to *ptr and store the value of 3119322992(referencing to the address of *ptr).

When I test pointer to pointer outside of a function, it does behave in this exact manner. Why it differs for pointer to pointer as an argument baffles me.

Can you explain to me what's happening here?

First of all what is a pointer? A pointer in C/C++ is just like any other variable with a type like int, char etc. But speciality of this variable is that unlike other variable it just hold the address of a memory location. Again that memory location also might be a pointer variable or any other regular variable( int or char).

Now what is pointer of pointer? A variable who can store the address of a pointer variable and that pointer variable might holding the address of another variable like:-

 int i = 10; //`i` is assign with a value  10 and `i` has its own address which we can get by `&i`;

 int *ptr1 = &i;// now ptr1 is pointer to `i` means ptr1 is assign with the
 //address of `i` hence if we dereference the address of *ptr1 we will get the value stored at that memory location

Now in your case

 void ptrTest(int **arg_ptr){
    printf("Address store in of **arg_ptr: %u\n",arg_ptr);    
}

So here it will work like below

int **arg_ptr = ptr1;//Wrong, `ptr1` is assign to `arg_ptr`, which is wrong because `arg_ptr` is a pointer to pointer type

So here you should store the address of a pointer but you are storing the address of a variable int which is i . Because address of i has been assign in statement int *ptr1 = &i; to ptr1. The correct assignment would be

arg_ptr = &ptr1; //address of a pointer not address of a int variable.

Now first dereferencing:-

  *arg_ptr; //value of a pointer ptr1 that means address of `i`

 *(*arg_ptr); or **arg_ptr;// we further dereferenced the address of ptr1 here, which is value 10

Now you should call your function like below:-

ptrTest(&ptr1);// address of a pointer.

ptrTest expects an argument of type int ** but you are passing int* . Your compiler should complain. You need to pass the address of ptr to the function.

ptrTest(&ptr1);  

Apart from that you should use %p specification to print address.

printf("Address of some_var: %p\n\n", (void*)&some_var);

When I compile your code I get a long list of errors:

"test.c", line 11: warning #2181-D: argument is incompatible with
          corresponding format string conversion
      printf("Address of some_var: %u\n\n", &some_var);
                                            ^

"test.c", line 12: warning #2181-D: argument is incompatible with
          corresponding format string conversion
      printf("Value stored in *ptr1 (references to some_var): %u\n", ptr1);
                                                                     ^

"test.c", line 13: warning #2181-D: argument is incompatible with
          corresponding format string conversion
      printf("Address of *ptr1 variable: %u\n\n", &ptr1);
                                                  ^

"test.c", line 14: warning #2167-D: argument of type "int *" is incompatible
          with parameter of type "int **"
      ptrTest(ptr1);
              ^

"test.c", line 18: warning #2181-D: argument is incompatible with
          corresponding format string conversion
      printf("Value stored in **arg_ptr (references to some_var): %u\n",arg_ptr);

Let's rewrite this code so it compiles without errors and is perhaps a little clearer:

#include <stdio.h>

void ptrTest(int **arg_ptr)
  {
  printf("Value stored in arg_ptr (points to ptr1): %#p\n", arg_ptr);
  printf("Value pointed to by arg_ptr (i.e. *arg_ptr - should be same as ptr1): %#p\n", *arg_ptr);
  printf("Value pointed to by *arg_ptr (i.e. **arg_ptr - should be same as some_var): %d\n", **arg_ptr);
  }

int main()
  {
  int some_var = 5;
  int *ptr1;

  ptr1 = &some_var;

  printf("some_var: %d\n", some_var);
  printf("Address of some_var: %#p\n\n", &some_var);
  printf("Value stored in ptr1 (should be address of some_var): %#p\n", ptr1);
  printf("Address of ptr1 variable: %#p\n\n", &ptr1);
  ptrTest(&ptr1);
  }

What got changed:

  1. Used signed int format in printf ( %d ) instead of unsigned format ( %u ).

  2. Used pointer format in printf ( %p ) when printing pointers.

  3. Added code to ptrTest to follow arg_ptr all the way back to the base target of the pointer chain.

  4. Added code to print the value of some_var

  5. Changed the wording of the output to clarify what's being shown, and which values should match up.

The new version compiles without errors (HP-UX default C compiler).

When the new version is run the following output is printed:

some_var: 5
Address of some_var: 0x7fffecd0

Value stored in ptr1 (should be address of some_var): 0x7fffecd0
Address of ptr1 variable: 0x7fffecd4

Value stored in arg_ptr (points to ptr1): 0x7fffecd4
Value pointed to by arg_ptr (i.e. *arg_ptr - should be same as ptr1): 0x7fffecd0
Value pointed to by *arg_ptr (i.e. **arg_ptr - should be same as some_var): 5

Now you can follow the chain of pointers forward and back to see which pointer points to which value, and how they all link up.

Best of luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM