2

I want to print where a variable is stored. I Google it and I found this:

int *p;
printf("memory location of ptr: %p\n",  (void *)p);

If I write this, is it right?

printf("memory location of ptr: %p\n",  &p);

I compiled it and I didn't get any errors or warnings. However, the above two commands didn’t return the same value!

yaylitzis
  • 5,354
  • 17
  • 62
  • 107

5 Answers5

7

Lets say you have these declarations:

int i;
int *p = &i;

It would look something like this in memory:

+---+     +---+
| p | --> | i |
+---+     +---+

If you then use &p you get a pointer to p, so you have this:

+----+     +---+     +---+
| &p | --> | p | --> | i |
+----+     +---+     +---+

So the value of p is the address of i, and the value of &p is the address of p. That's why you get different values.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Lets summurise: the `(void *)p` prints the memory location of the object that the pointer shows and the &p shows the memory location of the pointer itself.right? – yaylitzis Dec 04 '13 at 12:12
  • ok then a follow question! Since the value of p is the memory address of the object he shows.. Couldn't i just print the value of p? sth like that `printf("%s", p);` (i run it but i had an warning of format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int *’ so isn't right i guess... – yaylitzis Dec 04 '13 at 12:19
  • @Nat95 Since `p` points to an `int`, you of course have to print an integer (to begin with), and to get the value that `p` points to you have to use the dereference operator `*`, so do `printf("%d\n", *p);` – Some programmer dude Dec 04 '13 at 12:21
3

if I write this, is it right?

No. This is not right. For %p specifier you must have to cast it to void *. Your compiler should give warning about this:

warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int **’ [-Werror=format=]  

Read this answer. It says that:

The %p format requires an argument of type void*. If pointers of type int* and int(*)[10] have the same representation as void* and are passed as arguments in the same way, as is the case for most implementations, it's likely to work, but it's not guaranteed. You should explicitly convert the pointers to void*

Draft n1570; 7.21.6 Formatted input/output functions:

p The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.


but theses two statements don’t return the same value if I put both of them in the program.

Yes,it will not return the same value. P will give you the value of address of the variable p points to (pointee) while &p will give you the value of the address of pointer p itself. Cast &p to void *.

printf("memory location of ptr: %p\n",  (void *)&p);  
Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
  • Ok, but why I don't get any warnings? (I use ubuntu via VirtualBox) – yaylitzis Dec 04 '13 at 12:06
  • 1
    In C, all pointers can be implicitly casted to `void *`, as well as the opposite. – Some programmer dude Dec 04 '13 at 12:11
  • Enable your `Wextra` flag in your compiler settings . – haccks Dec 04 '13 at 12:32
  • @JoachimPileborg; Could you elaborate it more. – haccks Dec 04 '13 at 12:33
  • For example, `free` takes a `void *` argument, but you don't have to cast it. As well as `malloc` returns a `void *` but you don't have to cast that either. In fact, you *should* not cast `void *` arguments and returns, as that might hide subtle bugs when the functions are not properly declared. That is, this how it is in C, in C++ you have to cast. – Some programmer dude Dec 04 '13 at 12:37
  • @JoachimPileborg; Then why I am getting warning in case of `%p` specifier, specially ? – haccks Dec 04 '13 at 14:23
1

If you use the "&" operator on a pointer, you create a pointer to the pointer. So the result in your case would be an int**.

printf expects a void* when you use the %p specifier, therefore the first way is correct.

maxdev
  • 2,491
  • 1
  • 25
  • 50
0

As you have discovered, the two don't do the same thing.

The first will print the value stored in p. You would usually expect this to be the address of an int (though people do the darnedest things).

The second will print the address of p. However, you need to add a cast to void * for portability reasons, so the second should read

printf("memory location of ptr: %p\n", (void *)&p);

I want to print where a variable is stored.

So the answer to your question depends on which variable you are concerned with? For the int that p points to you want to use the first one. For the variable p itself you want to use the second.

NaotaSang
  • 506
  • 3
  • 6
0
#include <stdio.h>

int main()
{
    int i;
    int *x = &i;

    i = 8;
    printf("value of i is %d\n",i);
    printf("value of x is %d\n", *x);
    printf("address of x is %p\n",x);
    printf("address of i is %p\n",&i);
}

output:

~/workspace/C$ ./test

value of i is 8

value of x is 8

address of x is 0x7fff793b09c4

address of i is 0x7fff793b09c4

wbt11a
  • 798
  • 4
  • 12