The usage of %p in C

P

Pietro Cerutti

Tak said:
Hi :
I want to know how to use %p in the program.Help me!
Does it mean %x?

If you mean the printf-style format specifiers, %p is for pointers
types, while %x is for integers types and means "display the integer's
hexadecimal value".

Here's an example:
cat format.c
#include <stdio.h>

int main(void)
{
int i = 10;

printf("dec -> %d\n", i);
printf("hex -> %x\n", i);
printf("addr -> %p\n", &i);

return (0);
}
gcc -Wall -o format format.c && ./format
dec -> 10
hex -> a
addr -> 0xbfcc4894
 
R

Richard Bos

Tak said:
I want to know how to use %p in the program.Help me!

You use %p when you want to print an object pointer. Cast the pointer to
void * and pass it to printf(). Like this:

#include <stdio.h>

int main(void)
{
int object;

printf("The address of object is %p.\n", (void *)&object);

return 0;
}
Does it mean %x?

No. It means %p. It prints a pointer. _How_ that pointer is printed is
system-dependent. Like %x is a possibility. So is (segment like
%4.4X):(offset like %4.4X). So are many other options. It will, in all
likelyhood, depend on how pointers are usually printed on your platform.

Richard
 
R

Richard Heathfield

Pietro Cerutti <gahr_AT_gahr_DOT_ch_DO_NOT_SPAM> said:

printf("addr -> %p\n", &i);

Undefined behaviour. Use this instead:

printf("addr -> %p\n", (void *)&i);
 
J

jacob navia

Richard said:
Pietro Cerutti <gahr_AT_gahr_DOT_ch_DO_NOT_SPAM> said:



Undefined behaviour. Use this instead:

printf("addr -> %p\n", (void *)&i);

I think the cast is unnecessary, unless int * and void *
are of different sizes in your system...
 
G

Gilles Chehade

I think the cast is unnecessary, unless int * and void *
are of different sizes in your system...

even if they were, a void * isn't supposed to be able to store
a value held by another pointer of any kind ?

Gilles
 
M

Mark Bluemel

Tak said:
Hi :
I want to know how to use %p in the program.Help me!

Be more precise in describing your problem and we may be better able to
help.

What problem do you have in using "%p", presumably as a format mask in
printf()?

It's quite simple, it specifies that an argument to printf is a "void *"
and should be formatted as a pointer in an implementation-specific form.
Does it mean %x?

No - %x specifies that an argument is an unsigned int and is to be
formatted in hexadecimal form.
 
M

Mark Bluemel

Gilles said:
even if they were, a void * isn't supposed to be able to store
a value held by another pointer of any kind ?

The point is that it is possible, even if unlikely in most
architectures, for void * to have a different size and/or representation
to, for example, int *.

The %p format mask to printf() specifies that the argument is a void *,
not just "some pointer". If we are trying to be correct, rather than
simply getting away with it on some platform or other, we should pass a
void *.
 
M

Mark Bluemel

jacob said:
I think the cast is unnecessary, unless int * and void *
are of different sizes in your system...

Let's rephrase this. "If you know that int * and void * are represented
in the same way, both size and internal format, on your platform, AND
you never expect to use the code elsewhere, you can skip the cast".

Now for the approach that at least some of us prefer - "the
specification of printf() is that the %p mask indicates that an argument
is a pointer to void, therefore the correct usage is to pass a pointer
to void". This approach means we can write correct code without detailed
knowledge of the internals of the platform, and that code will be portable.
 
D

Denis Kasak

jacob said:
>
> I think the cast is unnecessary, unless int * and void *
> are of different sizes in your system...

The cast is necessary because it is required by the Standard.

The most obvious practical reason for this necessity may well be the one
you mention (sizes of pointers to different types differ), but that is
irrelevant. The cast should be there precisely to avoid worrying about that.
 
R

Richard Heathfield

Gilles Chehade said:
even if they were, a void * isn't supposed to be able to store
a value held by another pointer of any kind ?

Any object pointer can be converted to and from void * without loss of
information. The cast is required; in its absence, the behaviour is
undefined. I do not dispute that Mr Navia thinks the cast to be
unnecessary unless int * and void * are different sizes but, regardless of
his thoughts on the matter, the cast remains necessary. The proof is in
three parts, the first of which is in 7.19.6.1, in the definition of
fprintf:

p The argument shall be a pointer to void. The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner.

The second part of the proof is in 7.19.6.3, the definition of printf:

2 The printf function is equivalent to fprintf with the argument stdout
interposed before the arguments to printf.

The third is in 4.2:

2 If a ``shall'' or ``shall not'' requirement that appears outside of a
constraint is violated, the behavior is undefined.
 
G

Gilles Chehade

The point is that it is possible, even if unlikely in most
architectures, for void * to have a different size and/or representation
to, for example, int *.

The %p format mask to printf() specifies that the argument is a void *,
not just "some pointer". If we are trying to be correct, rather than
simply getting away with it on some platform or other, we should pass a
void *.

Thanks,

Gilles
 
G

Gilles Chehade

Gilles Chehade said:


Any object pointer can be converted to and from void * without loss of
information. The cast is required; in its absence, the behaviour is
undefined. I do not dispute that Mr Navia thinks the cast to be
unnecessary unless int * and void * are different sizes but, regardless of
his thoughts on the matter, the cast remains necessary. The proof is in
three parts, the first of which is in 7.19.6.1, in the definition of
fprintf:

p The argument shall be a pointer to void. The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner.

The second part of the proof is in 7.19.6.3, the definition of printf:

2 The printf function is equivalent to fprintf with the argument stdout
interposed before the arguments to printf.

The third is in 4.2:

2 If a ``shall'' or ``shall not'' requirement that appears outside of a
constraint is violated, the behavior is undefined.

Thanks,

Gilles
 
P

Pietro Cerutti

Mark said:
The point is that it is possible, even if unlikely in most
architectures, for void * to have a different size and/or representation
to, for example, int *.

The %p format mask to printf() specifies that the argument is a void *,
not just "some pointer". If we are trying to be correct, rather than
simply getting away with it on some platform or other, we should pass a
void *.

The correction is correct ;-)

Anyway, a question raises:

1) two pointer types are allowed to be of different sizes
2) the void pointer is guaranteed to store any other pointer's value
without loss of information
this leads to:
3) the size of a void pointer is guaranteed to be at least as big as the
size of any other pointers

if 3) is a correct deduction, then I don't see the point to impose that
an argument of printf used in conjunction with %p must be a void pointer.

if 3) is incorrect, how do we assure that a conversion to void * cannot
lead to a loss of information?

Thanks for clarifying this point.
 
R

Richard Bos

Mark Bluemel said:
Let's rephrase this. "If you know that int * and void * are represented
in the same way, both size and internal format, on your platform, AND
you never expect to use the code elsewhere,

_And_ are passed the same way to variadic functions...
_And_...
you can skip the cast".

I would not skip the cast for non-void pointers under any circumstances.
It is simply not worth the risk, and this is one of the few cases in C
where a mandatory cast actually _does_ make sense.

Richard
 
M

Mark Bluemel

Pietro said:
... a question raises:

1) two pointer types are allowed to be of different sizes

And formats...
2) the void pointer is guaranteed to store any other pointer's value
without loss of information
this leads to:
3) the size of a void pointer is guaranteed to be at least as big as the
size of any other pointers

Not necessarily. I used to work on a machine which had 32-bit and 48-bit
pointers which both actually had the same effective "precision". Both
actually addressed bytes in a 32-bit address space. Don't ask...
if 3) is a correct deduction, then I don't see the point to impose that
an argument of printf used in conjunction with %p must be a void pointer.

All printf can go on is the data you gave it. By giving a "%p" mask
you've said you are passing a void * pointer. Because this is a variadic
function, there will be no safety net provided by the compiler - nothing
will ensure that what you pass will be converted to a void *.

If you pass printf() something else, like an int *, you invoke undefined
behaviour. As ever, UB may turn out to do what you want, but it is not
guaranteed.
if 3) is incorrect, how do we assure that a conversion to void * cannot
lead to a loss of information?

That's the implementer's problem, not ours :)
 
M

Mark Bluemel

Richard said:
_And_ are passed the same way to variadic functions...
_And_...

Good points...
I would not skip the cast for non-void pointers under any circumstances.
It is simply not worth the risk, and this is one of the few cases in C
where a mandatory cast actually _does_ make sense.

Indeed.
 
R

Richard

Mark Bluemel said:
And formats...

I keep hearing this. Can you explain how,say, a "special" pointer can be
stored in a malloc'ed block of memory which basically returns a single
block from a common memory pool?
 
C

Christopher Benson-Manica

[comp.lang.c] jacob navia said:
Richard Heathfield wrote:
printf("addr -> %p\n", (void *)&i);
I think the cast is unnecessary, unless int * and void *
are of different sizes in your system...

if( sizeof(void*) != sizeof(int*) ) {
printf("addr -> %p\n", (void *)&i);
}
else {
printf("addr -> %p\n", &i);
}

Even given such "unwarranted chumminess with the implementation"
(which as has been noted elsethread is still not enough to guarantee
that the else clause will not break), doesn't this strike you as a
bit silly? Why not just use the cast?
 
R

Richard Bos

Richard said:
I keep hearing this. Can you explain how,say, a "special" pointer can be
stored in a malloc'ed block of memory which basically returns a single
block from a common memory pool?

Who was talking about malloc()ed blocks of memory? We were talking about
void *s and int *s. They can certainly be laid out differently in
memory, as long as converting from one to the other and back works.
Note: converting. Not reinterpreting the bit patterns. IOW,

int i, *int_ptr=&i;
void *void_ptr=int_ptr;
int *int_ptr2=void_ptr;

must work, and int_ptr2 must compare equal to int_ptr. This is because
the types of int_ptr, int_ptr2 and void_ptr are all known to the
compiler at the point of conversion.
This is not the case with pointers passed to variadic functions. A
variadic function does _not_ know that it has been passed an int *
instead of the void * it has been told to expect, and what's worse, it
has no way to find out. Therefore, when a variadic function - in this
case, printf() - believes that it needs a void *, it will try to read a
void *, and not an int *. No conversion takes place.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top