7
char  x = 'G';
char *p = &x;

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

Can someone tell me what exactly (void*)p means? I know that it is the same as p, as that also gives me the address of x, but why is this written as (void*)p?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Kai
  • 191
  • 3
  • 1
    The `%p` specifier requires `void*` to be passed as parameter. `(void*)p` is casting `p` to such. – Eugene Sh. Feb 08 '19 at 18:12
  • Well, I don't think that one is a duplicate. This one is more about casting. – Eugene Sh. Feb 08 '19 at 18:14
  • All of these downvotes are stupid: Kai is asking a legimate question. I'm just not sure if the question is "Q: What's a void *"?, or "Q: Why should I cast to (vooid *) here?" REFERENCES: https://stackoverflow.com/questions/692564/, https://stackoverflow.com/questions/24867814/ – paulsm4 Feb 08 '19 at 18:14
  • 1
    @paulsm4 I am afraid pure title contributed. I have edited the title (and retracted the downvote). I, for one, had no idea %p requires void pointer. – Suma Feb 08 '19 at 18:15
  • 2
    Thank you, Suma. Another potential duplicate is: [printf("%p") and casting to (void \*)](https://stackoverflow.com/questions/24867814/printfp-and-casting-to-void) – paulsm4 Feb 08 '19 at 18:17
  • The function `printf` is defined something like `int printf(const char *, ...)`. I don't remember there being a `print` function so I'll assume it's a function with the prototype `int print(const char*, void*)`. The `...` accepts anything. The `void*` requires a `void*` hence the cast – agbinfo Feb 08 '19 at 18:19
  • 3
    On the machine I learned to program C with (back in the days when the C standard was not yet a gleam in the eye — and before `void *` or `%p` existed), if you printed `short s; printf("0x%lX\n", &s); printf("0x%lX\n", (char *)&s);`, you would get different results because the machine used word oriented addressing. The same was true for any 'wider than `char`' type compared to the `char *` address for the same object. This meant you had to be excruciatingly careful to ensure that `malloc()` was declared before you used it, as otherwise everything blew up horribly. These days, it is easier. – Jonathan Leffler Feb 08 '19 at 18:19
  • @JonathanLeffler Any thoughts of C requiring `char *` and `void *` to be passed the same to `...` as [commented](https://stackoverflow.com/questions/54598093/why-is-pointer-casted-as-void-p-when-used-in-printf#comment95992755_54598134)? – chux - Reinstate Monica Feb 08 '19 at 18:31
  • 2
    @chux: C11 [§6.2.5 Types ¶28](http://port70.net/~nsz/c/c11/n1570.html#6.2.5p28) says: _A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.48)_ and footnote 48 says: _The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions._ I think they're required to be equivalent in all contexts, including `...` — but simply writing `0` in a `...` portion of an argument list does not necessarily create a pointer-sized value; use a cast. – Jonathan Leffler Feb 08 '19 at 18:34
  • @JonathanLeffler Yes the footnote is the clue I've missed. About 0, related is why `print ("%p" , NULL); print ("%d" , NULL); print ("%ld" , NULL);` are problems vs `print ("%p %d" , (void*) NULL, (int) NULL);` – chux - Reinstate Monica Feb 08 '19 at 18:39
  • @JonathanLeffler When making the `...` vs. `void*` comment, I was thinking more about the warnings that the compiler might give. – agbinfo Feb 08 '19 at 18:39

1 Answers1

12

The C standard says this about the %p format specifier for printf family functions (§ 7.21.6.2, paragraph 12)

The corresponding argument shall be a pointer to a pointer to void.

Pointers to different types may differ in their internal representation, except for void * and char * pointers, which are guaranteed to be the same size. However, any object pointer type is convertible to void *. So, to be sure that all %p variables are processed correctly by printf, they are required to be void *.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
  • 1
    Re “except for”: All pointers to structure types shall have the same representation and alignment requirements as each other (but may be different from `void *` and `char *`), per C 2018 6.2.5 28. And union pointers are the same as each other. And pointers to qualified or unqualified versions of compatible types are the same as each other. – Eric Postpischil Feb 08 '19 at 19:04