I've read a lot of answers about the %p
format specifier usage in C language here in Stack Overflow, but none seems to give an explanation as to why explicit cast to void*
is needed for all types but char*
.
I'm of course aware about the fact that this requirement to cast to or from void*
is tied with the use of variadic functions (see first comment of this answer) while non-mandatory otherwise.
Here's an example :
int i;
printf ("%p", &i);
Yields a warning about type incompatibility and that &i
shall be casted to void*
(as required by the standard, see again here).
Whereas this chunk of code compiles smoothly with no complaint about type casting whatsoever:
char * m = "Hello";
printf ("%p", m);
How does that come that char*
is "relieved" from this imperative?
PS: It's maybe worth adding that I work on x86_64 architecture, as pointer type size depends on it, and using gcc as compiler on linux with -W -Wall -std=c11 -pedantic
compiling options.
%p is a format specifier in C Programming language, that is used to work with pointers while writing a code in C.
In C we have seen different format specifiers. Here we will see another format specifier called %p. This is used to print the pointer type data.
The %p format specifier is used for printing the value of a pointer in C. This phenomenon is showed clearly in the coding example below. C. Copy #include<stdio.h> void main() { int i=100; printf("%d\n",i); int *pointer = &i; printf("%p\n",i); printf("%p",pointer); }
Originally Answered: What are the actual differences between %d, %u and %p format specifiers used in C to print the memory address of a variable? As you already explained %d is used for signed integers, while %u is for unsigned integers. %p is used to print pointer addresses.
There is no explicit cast needed for arguments of type char*
, as char *
has the same representation and alignment requirement as void *
.
Quoting C11
, chapter §6.2.5
A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. (48) [...]
and the footnote 48)
The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.
The C11 standard 6.2.5/28 says:
A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. 48)
with footnote 48 being:
The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.
However 7.21.6.1 ("The fprintf function") says about %p
:
The argument shall be a pointer to void.
This is apparently a contradiction. In my opinion, a sensible interpretation is to say that the intent of 6.2.5/28 is that void *
and char *
are in fact interchangeable as the types for function arguments which do not correspond to a prototype. (i.e. arguments to non-prototyped functions, or matching the ellipsis of a prototype of variadic function).
Apparently the compiler you're using takes a similar view.
To back this up, the specification of argument types in 7.21.6.1, if taken literally without regard to intent, has a lot of other inconsistencies that have to be disregarded in practice (e.g. it says that printf("%lx", -1);
is well-defined, but printf("%u", 1);
is undefined behaviour).
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