Is My Program OK?

Discussion in 'C Programming' started by Andy G., Feb 23, 2008.

  1. Andy G.

    Andy G. Guest

    Greetings!

    I am learning C and I came up with this program to test my knowledge.

    #include <stdio.h>
    #include <stdlib.h>
    int main(void)
    {
    char s[128];
    void *p;
    sprintf(s, "%p", malloc(0x10));
    puts(s);
    sscanf(s, "%p", &p);
    printf("%p\n", p);
    free(p);
    return 0;
    }

    Is it OK? Even if malloc returns NULL?

    One thing I am not sure of is what the size of s should be. Is 128
    enough? Or too much? How should I know how big to make it?

    Thanks in advance -- Andy!
    Andy G., Feb 23, 2008
    #1
    1. Advertising

  2. Andy G.

    Guest

    On Feb 23, 10:26 am, "Andy G." <> wrote:
    > Greetings!
    >
    > I am learning C and I came up with this program to test my knowledge.
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > int main(void)
    > {
    > char s[128];
    > void *p;
    > sprintf(s, "%p", malloc(0x10));
    > puts(s);
    > sscanf(s, "%p", &p);
    > printf("%p\n", p);
    > free(p);
    > return 0;
    >
    > }
    >
    > Is it OK? Even if malloc returns NULL?

    Yes, except the sprintf() part.
    > One thing I am not sure of is what the size of s should be. Is 128
    > enough? Or too much? How should I know how big to make it?

    You cannot know whether it will fit or not.
    You should instead use snprintf() and check the return value.
    Also, save the pointer somewhere, in case it does not fit in the
    buffer so you can free it.
    , Feb 23, 2008
    #2
    1. Advertising

  3. > You cannot know whether it will fit or not.
    Are you sure? This should do the trick:

    int mod = -1;
    int len = ((mod = sizeof(void*) % sizeof(char)) == 0) ? sizeof(void*)/
    sizeof(char) : sizeof(void*)/sizeof(char)+1;
    char s[len];
    Vitillo Roberto, Feb 23, 2008
    #3
  4. Andy G.

    Bartc Guest

    "Vitillo Roberto" <> wrote in message
    news:...
    >> You cannot know whether it will fit or not.

    > Are you sure? This should do the trick:
    >
    > int mod = -1;
    > int len = ((mod = sizeof(void*) % sizeof(char)) == 0) ? sizeof(void*)/
    > sizeof(char) : sizeof(void*)/sizeof(char)+1;
    > char s[len];


    I think if my life depended on getting len absolutely right, I would rather
    take my chances with len=128.

    Especially as your code seems to give len=4 :)

    --
    Bart
    Bartc, Feb 23, 2008
    #4
  5. Andy G.

    Roberto V. Guest

    Ups...
    int mod = -1;
    int len = ((mod = sizeof(void*)*2 % sizeof(char)) == 0) ?
    sizeof(void*)*2/sizeof(char) : sizeof(void*)*2/sizeof(char)+1;
    char s[len+1];

    Better now? ;)
    Roberto V., Feb 23, 2008
    #5
  6. Andy G.

    Guest

    On Feb 23, 1:45 pm, "Roberto V." <> wrote:
    > Ups...
    > int mod = -1;
    > int len = ((mod = sizeof(void*)*2 % sizeof(char)) == 0) ?
    > sizeof(void*)*2/sizeof(char) : sizeof(void*)*2/sizeof(char)+1;
    > char s[len+1];
    >
    > Better now? ;)


    What logic is that?
    Do you have any understanding of the problem I addressed?
    sizeof(void *)*2 % sizeof(char) will always 0 because sizeof(char) is
    guaranteed to be 1. N % 1 == 0.
    So, we completely ignore the first case, and let's see what's after
    the ':'
    sizeof(void *) * 2 / sizeof (char) + 1
    Let us assume sizeof (void *) is 4. 4 * 2 / 1 + 1 = 8 / 1 + 1 = 8 + 1
    = 9.
    I think I start to understand your logic (which, alas is still flawed)
    You want to calculate the N of bytes in the pointer size, so you can
    'predict' the size of it's hex representation.
    Ofcourse, the mistake here is that you *assume* the representation
    will be in hex.
    You also assume that EVEN if it's in hex, 0x will not be prefixed.
    0xHHHHHHHH is 11 in size and not 9.

    You *cannot* know the size.
    , Feb 23, 2008
    #6
  7. Andy G.

    santosh Guest

    wrote:

    > On Feb 23, 10:26 am, "Andy G." <> wrote:
    >> Greetings!
    >>
    >> I am learning C and I came up with this program to test my knowledge.
    >>
    >> #include <stdio.h>
    >> #include <stdlib.h>
    >> int main(void)
    >> {
    >> char s[128];
    >> void *p;
    >> sprintf(s, "%p", malloc(0x10));
    >> puts(s);
    >> sscanf(s, "%p", &p);
    >> printf("%p\n", p);
    >> free(p);
    >> return 0;
    >>
    >> }
    >>
    >> Is it OK? Even if malloc returns NULL?

    > Yes, except the sprintf() part.
    >> One thing I am not sure of is what the size of s should be. Is 128
    >> enough? Or too much? How should I know how big to make it?

    > You cannot know whether it will fit or not.
    > You should instead use snprintf() and check the return value.
    > Also, save the pointer somewhere, in case it does not fit in the
    > buffer so you can free it.


    One more minor point is to cast the argument to printf to a void *,
    since the %p specifier is defined as accepting a void pointer value
    only.

    Maybe also change 's' to unsigned char[].
    santosh, Feb 23, 2008
    #7
  8. Andy G.

    Guest

    On Feb 23, 2:33 pm, santosh <> wrote:
    > wrote:
    > > On Feb 23, 10:26 am, "Andy G." <> wrote:
    > >> Greetings!

    >
    > >> I am learning C and I came up with this program to test my knowledge.

    >
    > >> #include <stdio.h>
    > >> #include <stdlib.h>
    > >> int main(void)
    > >> {
    > >> char s[128];
    > >> void *p;
    > >> sprintf(s, "%p", malloc(0x10));
    > >> puts(s);
    > >> sscanf(s, "%p", &p);
    > >> printf("%p\n", p);
    > >> free(p);
    > >> return 0;

    >
    > >> }

    >
    > >> Is it OK? Even if malloc returns NULL?

    > > Yes, except the sprintf() part.
    > >> One thing I am not sure of is what the size of s should be. Is 128
    > >> enough? Or too much? How should I know how big to make it?

    > > You cannot know whether it will fit or not.
    > > You should instead use snprintf() and check the return value.
    > > Also, save the pointer somewhere, in case it does not fit in the
    > > buffer so you can free it.

    >
    > One more minor point is to cast the argument to printf to a void *,
    > since the %p specifier is defined as accepting a void pointer value
    > only.

    That is not needed in the source mr Andy G. posted.
    , Feb 23, 2008
    #8
  9. santosh <> writes:

    > wrote:
    >
    >> On Feb 23, 10:26 am, "Andy G." <> wrote:

    <snip>
    >>> #include <stdio.h>
    >>> #include <stdlib.h>
    >>> int main(void)
    >>> {
    >>> char s[128];
    >>> void *p;
    >>> sprintf(s, "%p", malloc(0x10));
    >>> puts(s);
    >>> sscanf(s, "%p", &p);
    >>> printf("%p\n", p);
    >>> free(p);
    >>> return 0;
    >>> }
    >>>
    >>> Is it OK? Even if malloc returns NULL?

    <snip>
    > One more minor point is to cast the argument to printf to a void *,
    > since the %p specifier is defined as accepting a void pointer value
    > only.


    In both cases it is a void * that is passed.

    --
    Ben.
    Ben Bacarisse, Feb 23, 2008
    #9
  10. Vitillo Roberto <> writes:

    >> You cannot know whether it will fit or not.

    > Are you sure? This should do the trick:
    >
    > int mod = -1;
    > int len = ((mod = sizeof(void*) % sizeof(char)) == 0) ? sizeof(void*)/
    > sizeof(char) : sizeof(void*)/sizeof(char)+1;
    > char s[len];


    Nothing about sizeof(void *) can tell you the required output size.
    It could tell you something about the possible number of different
    pointer values, but that is not the same thing. %p might produce:

    <segment: 0x2345 offset: 2998788765 in cluster main:24>

    who knows?

    --
    Ben.
    Ben Bacarisse, Feb 23, 2008
    #10
  11. Andy G.

    santosh Guest

    wrote:

    > On Feb 23, 2:33 pm, santosh <> wrote:
    >> wrote:
    >> > On Feb 23, 10:26 am, "Andy G." <> wrote:
    >> >> Greetings!

    >>
    >> >> I am learning C and I came up with this program to test my
    >> >> knowledge.

    >>
    >> >> #include <stdio.h>
    >> >> #include <stdlib.h>
    >> >> int main(void)
    >> >> {
    >> >> char s[128];
    >> >> void *p;
    >> >> sprintf(s, "%p", malloc(0x10));
    >> >> puts(s);
    >> >> sscanf(s, "%p", &p);
    >> >> printf("%p\n", p);
    >> >> free(p);
    >> >> return 0;

    >>
    >> >> }

    >>
    >> >> Is it OK? Even if malloc returns NULL?
    >> > Yes, except the sprintf() part.
    >> >> One thing I am not sure of is what the size of s should be. Is 128
    >> >> enough? Or too much? How should I know how big to make it?
    >> > You cannot know whether it will fit or not.
    >> > You should instead use snprintf() and check the return value.
    >> > Also, save the pointer somewhere, in case it does not fit in the
    >> > buffer so you can free it.

    >>
    >> One more minor point is to cast the argument to printf to a void *,
    >> since the %p specifier is defined as accepting a void pointer value
    >> only.

    > That is not needed in the source mr Andy G. posted.


    Ah yes. My bad.
    santosh, Feb 23, 2008
    #11
  12. wrote:
    >
    > On Feb 23, 1:45 pm, "Roberto V." <> wrote:

    [...attempt to calculate length of sprintf's "%p" output...]
    > > Better now? ;)

    >
    > What logic is that?

    [...]
    > You also assume that EVEN if it's in hex, 0x will not be prefixed.
    > 0xHHHHHHHH is 11 in size and not 9.


    It also assume that nothing bu the hex digits are output. There
    may be other things, like a ':' separating segment:eek:ffset, or any
    other assorted decorations.

    > You *cannot* know the size.


    <pedant>

    Well, you can "know" it at runtime, with snprintf():

    7.19.6.5p3

    The snprintf function returns the number of characters that
    would have been written had n been sufficiently large, not
    counting the terminating null character, or a negative value
    if an encoding error occurred.

    </pedant>

    --
    +-------------------------+--------------------+-----------------------+
    | Kenneth J. Brody | www.hvcomputer.com | #include |
    | kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
    +-------------------------+--------------------+-----------------------+
    Don't e-mail me at: <mailto:>
    Kenneth Brody, Feb 25, 2008
    #12
  13. Andy G.

    CBFalconer Guest

    Kenneth Brody wrote:
    > wrote:
    >

    .... snip ...
    >
    >> You also assume that EVEN if it's in hex, 0x will not be prefixed.
    >> 0xHHHHHHHH is 11 in size and not 9.

    >
    > It also assume that nothing bu the hex digits are output. There
    > may be other things, like a ':' separating segment:eek:ffset, or any
    > other assorted decorations.
    >
    >> You *cannot* know the size.

    >
    > <pedant>
    > Well, you can "know" it at runtime, with snprintf():
    >
    > 7.19.6.5p3
    >
    > The snprintf function returns the number of characters that
    > would have been written had n been sufficiently large, not
    > counting the terminating null character, or a negative value
    > if an encoding error occurred.
    > </pedant>


    The C standard for fprintf says:

    Returns

    [#14] The fprintf function returns the number of characters
    transmitted, or a negative value if an output or encoding
    error occurred.

    and for printf says:

    Returns

    [#3] The printf function returns the number of characters
    transmitted, or a negative value if an output or encoding
    error occurred.

    which seem to provide an adequate means of determining the size
    written. Similarly for sprintf. Amazingly enough, these also
    allow detecting i/o errors in the output stream.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Feb 25, 2008
    #13
  14. "Andy G." <> wrote:
    > #include <stdio.h>
    > #include <stdlib.h>
    > int main(void)
    > {
    >   char s[128];
    >   void *p;
    >   sprintf(s, "%p", malloc(0x10));
    >   puts(s);
    >   sscanf(s, "%p", &p);
    >   printf("%p\n", p);
    >   free(p);
    >   return 0;
    >
    > }
    >
    > Is it OK? Even if malloc returns NULL?
    >
    > One thing I am not sure of is what the size of s should
    > be. Is 128 enough? Or too much? How should I know how
    > big to make it?


    No, yes and this big respectively. :)

    Other advice notwithstanding, if you actually want to
    print a pointer, even with the possibility of scanning
    it back later, then you should print and scan the
    representation as an array of unsigned char. The size
    (of hex output say) can be computed at compile time.

    --
    Peter
    Peter Nilsson, Feb 26, 2008
    #14
  15. CBFalconer wrote:
    >
    > Kenneth Brody wrote:
    > > wrote:

    [... size needed for "%p" output ...]
    > >> You *cannot* know the size.

    > >
    > > <pedant>
    > > Well, you can "know" it at runtime, with snprintf():
    > >
    > > 7.19.6.5p3
    > >
    > > The snprintf function returns the number of characters that
    > > would have been written had n been sufficiently large, not
    > > counting the terminating null character, or a negative value
    > > if an encoding error occurred.
    > > </pedant>

    >
    > The C standard for fprintf says:

    [... returns length or negative for error ...]
    > and for printf says:

    [... returns length or negative for error ...]
    > which seem to provide an adequate means of determining the size
    > written. Similarly for sprintf. Amazingly enough, these also
    > allow detecting i/o errors in the output stream.


    But, how big should you make the buffer for sprintf(), as the OP
    was using?

    --
    +-------------------------+--------------------+-----------------------+
    | Kenneth J. Brody | www.hvcomputer.com | #include |
    | kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
    +-------------------------+--------------------+-----------------------+
    Don't e-mail me at: <mailto:>
    Kenneth Brody, Feb 26, 2008
    #15
  16. Andy G.

    Willem Guest

    CBFalconer wrote:
    ) The C standard for fprintf says:
    <snip> (returns the number printed, or negative)
    ) and for printf says:
    <snip>
    ) which seem to provide an adequate means of determining the size
    ) written. Similarly for sprintf.

    Indeed, you can check that sprintf has gone beyond the bounds of your
    buffer. _After_ it has clobbered whatever happened to be located behind
    it (or invoked some other form of UB). Oopsie.


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
    Willem, Feb 26, 2008
    #16
  17. On 26 Feb 2008 at 20:19, Kenneth Brody wrote:
    > CBFalconer wrote:
    >>
    >> Kenneth Brody wrote:
    >> > wrote:

    > [... size needed for "%p" output ...]
    >> >> You *cannot* know the size.
    >> >
    >> > <pedant>
    >> > Well, you can "know" it at runtime, with snprintf():
    >> >
    >> > 7.19.6.5p3
    >> >
    >> > The snprintf function returns the number of characters that
    >> > would have been written had n been sufficiently large, not
    >> > counting the terminating null character, or a negative value
    >> > if an encoding error occurred.
    >> > </pedant>

    >>
    >> The C standard for fprintf says:

    > [... returns length or negative for error ...]
    >> and for printf says:

    > [... returns length or negative for error ...]
    >> which seem to provide an adequate means of determining the size
    >> written. Similarly for sprintf. Amazingly enough, these also
    >> allow detecting i/o errors in the output stream.

    >
    > But, how big should you make the buffer for sprintf(), as the OP
    > was using?


    You can fprintf it to /dev/null (or NUL), collect the return value, and
    then make the buffer that big for sprinf() with the same format string
    and arguments.

    Of course, that can't be what CBF had in mind as it's off-topic, not
    portable, not C, can't discuss it, blah blah.
    Antoninus Twink, Feb 26, 2008
    #17
  18. Andy G.

    CBFalconer Guest

    Willem wrote:
    > CBFalconer wrote:
    >
    >> The C standard for fprintf says:

    > <snip> (returns the number printed, or negative)
    >> and for printf says:

    > <snip>
    >> which seem to provide an adequate means of determining the size
    >> written. Similarly for sprintf.

    >
    > Indeed, you can check that sprintf has gone beyond the bounds of
    > your buffer. _After_ it has clobbered whatever happened to be
    > located behind it (or invoked some other form of UB). Oopsie.


    You can know in advance the max length of most fields to be
    written. For strings, you can apply strlen. If you have room to
    absorb the max, you can always measure what was actually emitted.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Feb 27, 2008
    #18
  19. Andy G.

    jaysome Guest

    On Tue, 26 Feb 2008 15:19:33 -0500, Kenneth Brody
    <> wrote:

    >CBFalconer wrote:
    >>
    >> Kenneth Brody wrote:
    >> > wrote:

    >[... size needed for "%p" output ...]
    >> >> You *cannot* know the size.
    >> >
    >> > <pedant>
    >> > Well, you can "know" it at runtime, with snprintf():
    >> >
    >> > 7.19.6.5p3
    >> >
    >> > The snprintf function returns the number of characters that
    >> > would have been written had n been sufficiently large, not
    >> > counting the terminating null character, or a negative value
    >> > if an encoding error occurred.
    >> > </pedant>

    >>
    >> The C standard for fprintf says:

    >[... returns length or negative for error ...]
    >> and for printf says:

    >[... returns length or negative for error ...]
    >> which seem to provide an adequate means of determining the size
    >> written. Similarly for sprintf. Amazingly enough, these also
    >> allow detecting i/o errors in the output stream.

    >
    >But, how big should you make the buffer for sprintf(), as the OP
    >was using?


    The C Standard says this about the "%p" conversion specification:

    "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."

    This means that this program:

    #include <stdio.h>
    int main(void)
    {
    printf("%p\n", (void*)0);
    return 0;
    }

    can produce the following output in a strictly conforming
    implementation:

    The quick brown fox jumps over the lazy dog.

    It could also output the text of The Declaration of Independence or of
    the book War and Peace. In other words, strictly speaking, the answer
    to the OP's question is: we don't know and we can't say.

    Practically speaking, though, a buffer size that is a generous power
    of 2 will work. I'd be comfortable with s[16], but personally I'd use
    a very cheap s[32] just for good measure.

    In my experience, sprintf'ing a pointer value to a string (in, for
    example, a debug log message), requires that you use a size for the
    string that is sufficient in size by eyeballing it. For example:

    char s[128];
    sprintf("p is %p\n", (void*)p);

    Although the size 128 is, strictly speaking, not guaranteed to be
    sufficient in size to accomodate the "%p" conversion specification
    along with the accompanying text, it is sufficient for practical
    purposes, all things considered.

    --
    jay
    jaysome, Feb 27, 2008
    #19
  20. Andy G.

    santosh Guest

    jaysome wrote:

    > On Tue, 26 Feb 2008 15:19:33 -0500, Kenneth Brody
    > <> wrote:
    >
    >>CBFalconer wrote:
    >>>
    >>> Kenneth Brody wrote:
    >>> > wrote:

    >>[... size needed for "%p" output ...]
    >>> >> You *cannot* know the size.
    >>> >
    >>> > <pedant>
    >>> > Well, you can "know" it at runtime, with snprintf():
    >>> >
    >>> > 7.19.6.5p3
    >>> >
    >>> > The snprintf function returns the number of characters that
    >>> > would have been written had n been sufficiently large, not
    >>> > counting the terminating null character, or a negative value
    >>> > if an encoding error occurred.
    >>> > </pedant>
    >>>
    >>> The C standard for fprintf says:

    >>[... returns length or negative for error ...]
    >>> and for printf says:

    >>[... returns length or negative for error ...]
    >>> which seem to provide an adequate means of determining the size
    >>> written. Similarly for sprintf. Amazingly enough, these also
    >>> allow detecting i/o errors in the output stream.

    >>
    >>But, how big should you make the buffer for sprintf(), as the OP
    >>was using?

    >
    > The C Standard says this about the "%p" conversion specification:
    >
    > "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."
    >
    > This means that this program:
    >
    > #include <stdio.h>
    > int main(void)
    > {
    > printf("%p\n", (void*)0);
    > return 0;
    > }
    >
    > can produce the following output in a strictly conforming
    > implementation:
    >
    > The quick brown fox jumps over the lazy dog.
    >
    > It could also output the text of The Declaration of Independence or of
    > the book War and Peace. In other words, strictly speaking, the answer
    > to the OP's question is: we don't know and we can't say.
    >
    > Practically speaking, though, a buffer size that is a generous power
    > of 2 will work. I'd be comfortable with s[16], but personally I'd use
    > a very cheap s[32] just for good measure.
    >
    > In my experience, sprintf'ing a pointer value to a string (in, for
    > example, a debug log message), requires that you use a size for the
    > string that is sufficient in size by eyeballing it. For example:
    >
    > char s[128];
    > sprintf("p is %p\n", (void*)p);
    >
    > Although the size 128 is, strictly speaking, not guaranteed to be
    > sufficient in size to accomodate the "%p" conversion specification
    > along with the accompanying text, it is sufficient for practical
    > purposes, all things considered.


    I suppose the proper way to do this is:

    char *ptr = "hello";
    char *a;
    int n = snprintf(NULL, 0, "%p", ptr);
    if (n > 0) {
    a = malloc(n + 1);
    if (!a) exit(EXIT_FAILURE);
    else {
    int m;
    m = snprintf(a, n + 1, "%p", ptr);
    if (m < 0 || m < n) {
    /* error */
    }
    }
    }
    else /* error */
    santosh, Feb 27, 2008
    #20
    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. pipi
    Replies:
    1
    Views:
    616
    Joseph Millar
    Jul 21, 2003
  2. Rey
    Replies:
    4
    Views:
    10,932
    Roedy Green
    Dec 12, 2003
  3. ola
    Replies:
    3
    Views:
    710
    Marco Schmidt
    Feb 16, 2004
  4. Parvsandhu
    Replies:
    2
    Views:
    411
    Thomas Weidenfeller
    Jul 11, 2005
  5. Replies:
    1
    Views:
    509
    Andrew Thompson
    Oct 31, 2005
Loading...

Share This Page