lord.garbage
lord.garbage

Reputation: 5970

Printing address a pointer points to, value the address points to, and the address of the pointer itself

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

Upvotes: 8

Views: 7002

Answers (1)

chqrlie
chqrlie

Reputation: 145287

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.

Upvotes: 4

Related Questions