The usage of %p in C

Discussion in 'C Programming' started by Tak, Sep 25, 2007.

  1. Tak

    Tak Guest

    Hi :
    I want to know how to use %p in the program.Help me!
    Does it mean %x?
     
    Tak, Sep 25, 2007
    #1
    1. Advertisements

  2. 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:
    #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);
    }
    dec -> 10
    hex -> a
    addr -> 0xbfcc4894
     
    Pietro Cerutti, Sep 25, 2007
    #2
    1. Advertisements

  3. Tak

    Richard Bos Guest

    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;
    }
    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
     
    Richard Bos, Sep 25, 2007
    #3
  4. Pietro Cerutti <gahr_AT_gahr_DOT_ch_DO_NOT_SPAM> said:

    Undefined behaviour. Use this instead:

    printf("addr -> %p\n", (void *)&i);
     
    Richard Heathfield, Sep 25, 2007
    #4
  5. Tak

    jacob navia Guest

    I think the cast is unnecessary, unless int * and void *
    are of different sizes in your system...
     
    jacob navia, Sep 25, 2007
    #5
  6. even if they were, a void * isn't supposed to be able to store
    a value held by another pointer of any kind ?

    Gilles
     
    Gilles Chehade, Sep 25, 2007
    #6
  7. Tak

    Mark Bluemel Guest

    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.
    No - %x specifies that an argument is an unsigned int and is to be
    formatted in hexadecimal form.
     
    Mark Bluemel, Sep 25, 2007
    #7
  8. Tak

    Mark Bluemel Guest

    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 *.
     
    Mark Bluemel, Sep 25, 2007
    #8
  9. Tak

    Mark Bluemel Guest

    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.
     
    Mark Bluemel, Sep 25, 2007
    #9
  10. Tak

    Denis Kasak Guest

    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.
     
    Denis Kasak, Sep 25, 2007
    #10
  11. 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.
     
    Richard Heathfield, Sep 25, 2007
    #11
  12. Thanks,

    Gilles
     
    Gilles Chehade, Sep 25, 2007
    #12
  13. Thanks,

    Gilles
     
    Gilles Chehade, Sep 25, 2007
    #13
  14. 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.
     
    Pietro Cerutti, Sep 25, 2007
    #14
  15. Tak

    Richard Bos Guest

    _And_ are passed the same way to variadic functions...
    _And_...
    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
     
    Richard Bos, Sep 25, 2007
    #15
  16. Tak

    Mark Bluemel Guest

    And formats...
    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...
    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.
    That's the implementer's problem, not ours :)
     
    Mark Bluemel, Sep 25, 2007
    #16
  17. Tak

    Mark Bluemel Guest

    Good points...
    Indeed.
     
    Mark Bluemel, Sep 25, 2007
    #17
  18. Tak

    Richard Guest

    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?
     
    Richard, Sep 25, 2007
    #18
  19. 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?
     
    Christopher Benson-Manica, Sep 25, 2007
    #19
  20. Tak

    Richard Bos Guest

    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
     
    Richard Bos, Sep 25, 2007
    #20
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.