I wrote a little program to familiarize myself with pointers and relations between them a little more. In order to do this I wrote a small piece of code that just declares and initializes an integer a
, then declares a pointer *p
to the address of a
and then goes on deeper to assign a pointer to a pointer *pp
and so on so far up to ****pppp
. If I understood pointers correctly a pointer to a pointer to a ... basically works like this:
Address of pointer (or integer) itself: 0x7fff08d1c658 0x7fff08d1c660 0x7fff08d1c668 0x7fff08d1c670 0x7fff08d1c67c
↑ ↑ ↑ ↑ ↑
pppp --> ppp --> pp --> p --> a = 42
↓ ↓ ↓ ↓
Address pointer points to: 0x7fff08d1c660 0x7fff08d1c668 0x7fff08d1c670 0x7fff08d1c67c
The addresses on the diagonal have to be identical because the previous pointer always points to the address of the next pointer which it has been assigned. Now I want to check this in a program using printf()
calls and here I am unsure if the way I print the address the more elaborate pointers **pp
, ***ppp
, and ****pppp
point to and how I print the addresses of these pointers themselves are correct. Could someone point out possible mistakes? Here is the code followed by its output:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a;
int *p;
int **pp;
int ***ppp;
int ****pppp;
a = 42;
/* Take the address of a */
p = &a;
/* Take the address of p */
pp = &p;
/* Take the address of pp */
ppp = &pp;
/* Take the address of ppp */
pppp = &ppp;
printf("Address of int &a: %p\n", &a);
printf("value of a: %d\n\n", a);
printf("Address where p points to via (void *)p: %p\n", (void *)p);
printf("Value that *p points to via *p: %d\n", *p);
printf("Address of *p itself via (void *)&p: %p\n\n", (void *)&p);
printf("Address where pp points to via (void *)pp: %p\n", (void *)pp);
printf("Value that **pp points to via **pp: %d\n", **pp);
printf("Address of **pp itself via (void *)&pp: %p\n\n", (void *)&pp);
printf("Address where ppp points to via (void *)ppp: %p\n", (void *)ppp);
printf("Value that ***ppp points to via ***ppp: %d\n", ***ppp);
printf("Address of ***ppp itself via (void *)&ppp: %p\n\n", (void *)&ppp);
printf("Address where pppp points to via (void *)pppp: %p\n", (void *)pppp);
printf("Value that ****pppp points to via ****pppp: %d\n", ****pppp);
printf("Address of ****pppp itself via (void *)&pppp: %p\n", (void *)&pppp);
return EXIT_SUCCESS;
}
Output:
Address of int &a: 0x7fff08d1c67c
value of a: 42
Address where p points to via (void *)p: 0x7fff08d1c67c
Value that *p points to via *p: 42
Address of *p itself via (void *)&p: 0x7fff08d1c670
Address where pp points to via (void *)pp: 0x7fff08d1c670
Value that **pp points to via **pp: 42
Address of **pp itself via (void *)&pp: 0x7fff08d1c668
Address where ppp points to via (void *)ppp: 0x7fff08d1c668
Value that ***ppp points to via ***ppp: 42
Address of ***ppp itself via (void *)&ppp: 0x7fff08d1c660
Address where pppp points to via (void *)pppp: 0x7fff08d1c660
Value that ****pppp points to via ****pppp: 42
Address of ****pppp itself via (void *)&pppp: 0x7fff08d1c658
You can print a pointer value using printf with the %p format specifier. To do so, you should convert the pointer to type void * first using a cast (see below for void * pointers), although on machines that don't have different representations for different pointer types, this may not be necessary.
Put another way, the pointer does not hold a value in the traditional sense; instead, it holds the address of another variable. A pointer "points to" that other variable by holding a copy of its address. Because a pointer holds an address rather than a value, it has two parts. The pointer itself holds the address.
Using a Pointer: To access address of a variable to a pointer, we use the unary operator & (ampersand) that returns the address of that variable. For example &x gives us address of variable x.
How do I print the address stored in the pointer in C++? int *ptr = &var; printf("%p", ptr); That will print the address stored in ptr will be printed.
Your code is mostly correct: you understand that printf
prints the value of pointers with the %p
conversion specifier. The actual output is implementation specific but can be parsed back into a pointer value by scanf
with the same %p
specifier.
There is one small detail you got wrong in printf("Address of int &a: %p\n", &a);
: pointers should always be converted to void *
when passed to printf
as the value to convert for the %p
specifier. The reason for this is subtle: on some architectures, pointers to different types may have a different representation, including a different size, and may be passed to printf
in a different way. Converting the pointer to void *
ensures that it will be passed in the form and manner expected by the printf
function.
This conversion is not automatic as printf
takes a variable number of arguments of different types, these arguments are passed in a manner specific to vararg
functions: for instance float
values are converted to and passed as double
, but various pointer types are not converted to void *
, so you must write this conversion explicitly with a (void *)
cast.
Examples of architectures with different pointer representations tend to be less popular nowadays, but older programmers may remember the days of near
and far
pointers and the various memory models where function and data pointers had a different size.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With