sprintf problem

Discussion in 'C++' started by William Payne, Sep 13, 2004.

  1. Hello, I want to display the address a pointer points to in hexadecimal form
    in the same way my debugger displays it.
    Say I have P* ptr; where P is some type.

    I tried:
    std::sprintf(message, "%#0x, (unsigned int)ptr);

    But that gives me: 0xFFFF for example, when I want 0x0000FFFF, i.e., I dont
    want to drop any leading zeros. I know this is just a small cosmetic
    problem, but I still would like to know how to accomplish this.

    Thanks for any replies!

    / WP
     
    William Payne, Sep 13, 2004
    #1
    1. Advertising

  2. William Payne

    Mike Wahler Guest

    "William Payne" <> wrote in message
    news:ci57mr$4cv$...
    > Hello, I want to display the address a pointer points to in hexadecimal

    form
    > in the same way my debugger displays it.
    > Say I have P* ptr; where P is some type.
    >
    > I tried:
    > std::sprintf(message, "%#0x, (unsigned int)ptr);
    >
    > But that gives me: 0xFFFF for example, when I want 0x0000FFFF, i.e., I

    dont
    > want to drop any leading zeros. I know this is just a small cosmetic
    > problem, but I still would like to know how to accomplish this.
    >
    > Thanks for any replies!


    #include <stdio.h>

    #define char_count (sizeof (unsigned int) * 2)

    int main()
    {
    unsigned int i = 0;
    int *ptr = &i;
    char message[2 * sizeof *ptr] = {0};

    sprintf(message, "%0*x", 2 * sizeof ptr, (unsigned int)ptr);

    puts(message);
    return 0;
    }

    Notes:

    The result of casting a pointer to unsigned int is implementation defined.

    The format specifier indicating a pointer is %p.

    The format of the text produced with the %p specifier is implementation
    defined.

    The size of type 'unsigned int' is not necessarily four bytes (but must be
    at least two bytes).

    The size of a byte is not necessarily eight bits (but must be at
    least eight bits).

    IOW: the above code is not portable.

    -Mike
     
    Mike Wahler, Sep 14, 2004
    #2
    1. Advertising

  3. William Payne

    Mike Wahler Guest

    "Mike Wahler" <> wrote in message
    news:Ehq1d.367$...
    > #include <stdio.h>
    >
    > #define char_count (sizeof (unsigned int) * 2)


    This macro is not used. Just a 'mental note'
    I forgot to throw away. :)

    -Mike
     
    Mike Wahler, Sep 14, 2004
    #3
  4. William Payne

    Mike Wahler Guest

    "Mike Wahler" <> wrote in message
    news:amq1d.372$...
    >
    > "Mike Wahler" <> wrote in message
    > news:Ehq1d.367$...


    Using C++ IOStreams:

    #include <iomanip>
    #include <ios>
    #include <iostream>
    #include <sstream>

    int main()
    {
    int i = 0;
    int *ptr = &i;
    std::eek:stringstream oss;

    oss << std::hex
    << std::setfill('0')
    << std::setw(2* sizeof *ptr)
    << ptr
    << '\n';

    std::cout << oss.str().c_str() << '\n';
    return 0;
    }


    -Mike
     
    Mike Wahler, Sep 14, 2004
    #4
  5. "Mike Wahler" <> wrote in message
    news:zsq1d.377$...
    >
    > "Mike Wahler" <> wrote in message
    > news:amq1d.372$...
    >>
    >> "Mike Wahler" <> wrote in message
    >> news:Ehq1d.367$...

    >
    > Using C++ IOStreams:
    >
    > #include <iomanip>
    > #include <ios>
    > #include <iostream>
    > #include <sstream>
    >
    > int main()
    > {
    > int i = 0;
    > int *ptr = &i;
    > std::eek:stringstream oss;
    >
    > oss << std::hex
    > << std::setfill('0')
    > << std::setw(2* sizeof *ptr)
    > << ptr
    > << '\n';
    >
    > std::cout << oss.str().c_str() << '\n';
    > return 0;
    > }
    >
    >
    > -Mike
    >
    >


    Thanks Mike! This last example is totally portable? I need portability
    across MSVC 7.1 and GCC 3.4.2, but I prefer using completely standard
    methods that does not rely on undefined behaviour.

    / WP
     
    William Payne, Sep 14, 2004
    #5
  6. William Payne

    Mike Wahler Guest

    "William Payne" <> wrote in message
    news:ci5csb$6il$...
    >
    > "Mike Wahler" <> wrote in message
    > news:zsq1d.377$...
    > >
    > > "Mike Wahler" <> wrote in message
    > > news:amq1d.372$...
    > >>
    > >> "Mike Wahler" <> wrote in message
    > >> news:Ehq1d.367$...

    > >
    > > Using C++ IOStreams:
    > >
    > > #include <iomanip>
    > > #include <ios>
    > > #include <iostream>
    > > #include <sstream>
    > >
    > > int main()
    > > {
    > > int i = 0;
    > > int *ptr = &i;
    > > std::eek:stringstream oss;
    > >
    > > oss << std::hex
    > > << std::setfill('0')
    > > << std::setw(2* sizeof *ptr)
    > > << ptr
    > > << '\n';
    > >
    > > std::cout << oss.str().c_str() << '\n';
    > > return 0;
    > > }
    > >
    > >
    > > -Mike
    > >
    > >

    >
    > Thanks Mike! This last example is totally portable?


    No. The same issues exits about conversion from integer
    to pointer types, and about type size assumptions.

    > I need portability
    > across MSVC 7.1 and GCC 3.4.2,


    The above isn't *universally* portable, but should be portable
    among most PC operating systems.

    >but I prefer using completely standard
    > methods


    There's no standard way to convert an integer to a pointer.
    You can further generalize by factoring 'CHAR_BIT' into the
    calculation of the output field width. But you need only
    be concerned about this if you intend to port to systems
    where 'CHAR_BIT' != 8.

    >that does not rely on undefined behaviour.


    Note that undefined behavior and implementation defined behavior
    are distinct specifications. The above code has implementation
    defined behavior, not undefined.

    -Mike
     
    Mike Wahler, Sep 14, 2004
    #6
  7. William Payne

    Jack Klein Guest

    On Mon, 13 Sep 2004 23:44:36 GMT, "Mike Wahler"
    <> wrote in comp.lang.c++:


    > Notes:
    >
    > The result of casting a pointer to unsigned int is implementation defined.


    If and only if unsigned int is large enough to hold the pointer. See
    paragraph 4 of 5.2.10 reinterpret_cast.

    > The format specifier indicating a pointer is %p.
    >
    > The format of the text produced with the %p specifier is implementation
    > defined.
    >
    > The size of type 'unsigned int' is not necessarily four bytes (but must be
    > at least two bytes).


    No, it must not.

    > The size of a byte is not necessarily eight bits (but must be at
    > least eight bits).


    Taking your last two statements above, you should be able to see why I
    objected to the first one. I'm working on a 16-bit DSP right now
    where CHAR_BIT is 16 and sizeof(unsigned int) is 1. It has a
    reasonably conforming free-standing C++ implementation.

    I have also used a 32-bit DSP where all of the integer types, char
    through long, all had 32 bits and sizeof == 1. C only though, it
    didn't have a C++ compiler.

    > IOW: the above code is not portable.
    >
    > -Mike


    The code isn't even necessarily defined. On 16-bit platforms with 32
    bit pointers (MS-DOS, TI2812, Philips XA, for example), the behavior
    is undefined. Likewise on a lot of the newer 64-bit Windows/*nix
    implementations, where ints have 32 bits and pointers have 64.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Sep 14, 2004
    #7
  8. William Payne

    Mike Wahler Guest

    "Jack Klein" <> wrote in message
    news:eek:...
    > On Mon, 13 Sep 2004 23:44:36 GMT, "Mike Wahler"
    > <> wrote in comp.lang.c++:
    >
    >
    > > Notes:
    > >
    > > The result of casting a pointer to unsigned int is implementation

    defined.
    >
    > If and only if unsigned int is large enough to hold the pointer. See
    > paragraph 4 of 5.2.10 reinterpret_cast.
    >
    > > The format specifier indicating a pointer is %p.
    > >
    > > The format of the text produced with the %p specifier is implementation
    > > defined.
    > >
    > > The size of type 'unsigned int' is not necessarily four bytes (but must

    be
    > > at least two bytes).

    >
    > No, it must not.


    Right. Should have said "at least sixteen bits."

    >
    > > The size of a byte is not necessarily eight bits (but must be at
    > > least eight bits).

    >
    > Taking your last two statements above, you should be able to see why I
    > objected to the first one.


    Yes. :)

    >I'm working on a 16-bit DSP right now
    > where CHAR_BIT is 16 and sizeof(unsigned int) is 1. It has a
    > reasonably conforming free-standing C++ implementation.
    >
    > I have also used a 32-bit DSP where all of the integer types, char
    > through long, all had 32 bits and sizeof == 1. C only though, it
    > didn't have a C++ compiler.
    >
    > > IOW: the above code is not portable.
    > >
    > > -Mike

    >
    > The code isn't even necessarily defined. On 16-bit platforms with 32
    > bit pointers (MS-DOS, TI2812, Philips XA, for example), the behavior
    > is undefined.


    Which specific expressions are the trouble (i.e. undefined
    rather than imp-defined)?

    -Mike
     
    Mike Wahler, Sep 14, 2004
    #8
  9. William Payne

    Jack Klein Guest

    On Tue, 14 Sep 2004 04:08:57 GMT, "Mike Wahler"
    <> wrote in comp.lang.c++:

    > "Jack Klein" <> wrote in message
    > news:eek:...
    > > On Mon, 13 Sep 2004 23:44:36 GMT, "Mike Wahler"
    > > <> wrote in comp.lang.c++:
    > >
    > >
    > > > Notes:
    > > >
    > > > The result of casting a pointer to unsigned int is implementation

    > defined.
    > >
    > > If and only if unsigned int is large enough to hold the pointer. See
    > > paragraph 4 of 5.2.10 reinterpret_cast.
    > >
    > > > The format specifier indicating a pointer is %p.
    > > >
    > > > The format of the text produced with the %p specifier is implementation
    > > > defined.
    > > >
    > > > The size of type 'unsigned int' is not necessarily four bytes (but must

    > be
    > > > at least two bytes).

    > >
    > > No, it must not.

    >
    > Right. Should have said "at least sixteen bits."
    >
    > >
    > > > The size of a byte is not necessarily eight bits (but must be at
    > > > least eight bits).

    > >
    > > Taking your last two statements above, you should be able to see why I
    > > objected to the first one.

    >
    > Yes. :)
    >
    > >I'm working on a 16-bit DSP right now
    > > where CHAR_BIT is 16 and sizeof(unsigned int) is 1. It has a
    > > reasonably conforming free-standing C++ implementation.
    > >
    > > I have also used a 32-bit DSP where all of the integer types, char
    > > through long, all had 32 bits and sizeof == 1. C only though, it
    > > didn't have a C++ compiler.
    > >
    > > > IOW: the above code is not portable.
    > > >
    > > > -Mike

    > >
    > > The code isn't even necessarily defined. On 16-bit platforms with 32
    > > bit pointers (MS-DOS, TI2812, Philips XA, for example), the behavior
    > > is undefined.

    >
    > Which specific expressions are the trouble (i.e. undefined
    > rather than imp-defined)?


    The C++ standard says (5.2.10 Reinterpret cast, p4)

    "A pointer can be explicitly converted to any integral type large
    enough to hold it. The mapping function is implementation defined
    [Note: it is intended to be unsurprising to those who know the
    addressing structure of the underlying machine. ]"

    This is the old undefined behavior because one or more cases are
    specifically defined and the case under discussion is not one of them.
    It is undefined by lack of definition. The fact that a pointer may be
    explicitly converted by reinterpret_cast (or C cast) to any integer
    type enough to hold it implicitly states that it may not be converted
    to an integer type that is not wide enough to hold it.

    In this case, I like the wording of the C standard better, it is more
    explicit (C99 6.3.2.3 Pointers p6):

    "Any pointer type may be converted to an integer type. Except as
    previously specified, the result is implementation-defined. If the
    result cannot be represented in the integer type, the behavior is
    undefined. The result need not be in the range of values of any
    integer type."

    C99 provides for (optional) typedefs for intptr_t and uintptr_t, which
    an implementation may define in <stdint.h> (almost certain to become
    <cstdint> some day) if such types exist that can hold any pointer
    type.

    So on a CHAR_BIT 8 implementation:

    double d = 50000.0;
    double *dp = & d;
    unsigned char uc;

    uc = d; /* range exceeded, undefined behavior */
    uc = dp; /* since pointers must be wider than 8 bits, ub */

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Sep 14, 2004
    #9
  10. William Payne

    Vinod Patel Guest

    "William Payne" <> wrote in message news:<ci57mr$4cv$>...
    > Hello, I want to display the address a pointer points to in hexadecimal form
    > in the same way my debugger displays it.
    > Say I have P* ptr; where P is some type.
    >
    > I tried:
    > std::sprintf(message, "%#0x, (unsigned int)ptr);
    >
    > But that gives me: 0xFFFF for example, when I want 0x0000FFFF, i.e., I dont
    > want to drop any leading zeros. I know this is just a small cosmetic
    > problem, but I still would like to know how to accomplish this.
    >
    > Thanks for any replies!
    >
    > / WP


    Assuming there are 8 octets for an address:-
    std::sprintf(message, "0x%08x", (unsigned int)ptr);
    should serve your purpose.

    Vinod
     
    Vinod Patel, Sep 14, 2004
    #10
  11. William Payne

    ma740988 Guest

    Jack Klein <> wrote in message news:<>...
    > On Mon, 13 Sep 2004 23:44:36 GMT, "Mike Wahler"

    [...]

    >
    > I have also used a 32-bit DSP where all of the integer types, char
    > through long, all had 32 bits and sizeof == 1. C only though, it
    > didn't have a C++ compiler.
    >
    > > IOW: the above code is not portable.
    > >
    > > -Mike

    >
    > The code isn't even necessarily defined. On 16-bit platforms with 32
    > bit pointers (MS-DOS, TI2812, Philips XA, for example), the behavior
    > is undefined. Likewise on a lot of the newer 64-bit Windows/*nix
    > implementations, where ints have 32 bits and pointers have 64.


    It's interesting working with the 2812 and trying to maintain
    portability with - for our purposes - a power pc.

    ifdef 2812
    // 16 bit character
    else
    //
    etc
     
    ma740988, Sep 15, 2004
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Huey

    sprintf: the format problem

    Huey, Dec 19, 2003, in forum: C Programming
    Replies:
    2
    Views:
    331
    Robert Stankowic
    Dec 19, 2003
  2. Replies:
    24
    Views:
    1,183
    Greg Comeau
    Oct 30, 2005
  3. Henryk

    Format problem with sprintf

    Henryk, Aug 18, 2006, in forum: C Programming
    Replies:
    12
    Views:
    866
    Martin Ambuhl
    Aug 22, 2006
  4. MJK

    Problem with sprintf

    MJK, Mar 4, 2010, in forum: C Programming
    Replies:
    1
    Views:
    501
    Keith Thompson
    Mar 4, 2010
  5. Replies:
    2
    Views:
    179
Loading...

Share This Page