-2

What is the address here ?

int main(void) {

    int i = 5;
    int *p;
    p = &i;

    printf("%d\n",*p);
    printf("%d\n",i);
    printf("%d\n",p);
    printf("%d\n",&i);
    printf("%p\n",p);
    printf("%p\n",&i);

    return 0;
}

output:

5
5
-7530484
-7530484
0xff8d180c
0xff8d180c

those are the outputs but why p gives me -7530484 i guess it must be pointer but then what is this 0xff8d180c ?

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
alkanschtein
  • 305
  • 1
  • 13

1 Answers1

2

In your code,

printf("%d\n",p);
printf("%d\n",&i);

invokes undefined behavior. Don't do that.

The ideal way of printing any pointer type is

  • use %p format specifier
  • cast the argument to void *

To elaborate on a bit on the seen output part, any argument supplied in conjunction with a %d format specifier would be interpreted as int type. The supplied argument here is actually of type int * (pointer type) and an int and an int * are not compatible types anyway which causes the UB. There's no guarantee of reproducibility of the output you're seeing in this case, it can very well show some other garbage value for some other platform / environment.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • It is not the "ideal", but the only correct and portable way. (unless you print function pointers which cannot be cast to `void *` portably. – too honest for this site Jan 05 '17 at 13:08
  • @Olaf: I wouldn't say it's the *only* way. E.g. this should also work: `printf("%.*" PRIxPTR "\n", (int)sizeof(uintptr_t), (uintptr_t)(void*)p);`. Of course, the `%p` method is both simpler *and* more portable (since the existance of `uintptr_t` isn't guaranteed, though it's practically ubiquitous) --- but it's still not the *only* way in most cases. – Tim Čas Jan 05 '17 at 14:07
  • @TimČas: You really should read comments carefully. I clearly stated "**portable**"! As you write yourself, there is no guarantee `uintptr_t` exists, nor that a pointer cast to it shows any useful value, – too honest for this site Jan 05 '17 at 14:13
  • @Olaf: It must be a distinct value, which is what matters in the end (since conversion from `uintptr_t` to `void*` must also work without loss of information). Hence, it must be *some* sort of a useful value. It is very portable, and pretty much the only option if one needs more control (so it's *more* portable in many ways, since the representation of `%p` is implementation-defined). – Tim Čas Jan 05 '17 at 14:37
  • "without loss of information" - that's not correct! The conversion must be from `void *` to `uintptr_t` and back without loss of information. That does not imply there is no loss for the conversion of only `uintptr_t` to `void *`, though. Simply put: the implementation can remove unnecessary information from the integer, which will still be shown in the `printf` output. Nevertheless, you completely ignored my point, as it is not portable, since `uintptr_t` is not guaranteed. This makes your comments more a "I want to say something, too". Thus I'll leave this pointless discussion here. – too honest for this site Jan 05 '17 at 15:02