printf("%p\n", (void *)0);

Discussion in 'C Programming' started by infobahn, Mar 5, 2005.

  1. infobahn

    infobahn Guest

    printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */
     
    infobahn, Mar 5, 2005
    #1
    1. Advertising

  2. infobahn

    G Fernandes Guest

    infobahn wrote:
    > printf("%p\n", (void *)0); /* UB, or not? Please explain your answer.

    */

    I don't think there is anything in the standard that makes this UB.
    You are not dereferencing a NULL pointer (which is UB) and it's the
    value of the poitner (address) that is used here.
     
    G Fernandes, Mar 5, 2005
    #2
    1. Advertising

  3. In article <>,
    infobahn <> wrote:
    :printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */

    Depends what you mean by "UB". All that the standard mandates about
    %p is that the implimentation will print -something- out, and that
    if scanf("%p") is used to read it back in within the same execution
    session then the result will compare equal to the original pointer.
    -What- is printed is undefined -- it need not even be numeric.
    It could print out verses from the Koran... translated into Farsi...
    though admittedly you are more likely to get snippets of dialogue
    from "Gilligan's Island".
    --
    Entropy is the logarithm of probability -- Boltzmann
     
    Walter Roberson, Mar 6, 2005
    #3
  4. infobahn

    CBFalconer Guest

    infobahn wrote:
    >
    > printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */


    UB, due to lack of prototype for printf, and appearing outside of
    the body of a function.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
     
    CBFalconer, Mar 6, 2005
    #4
  5. infobahn <> writes:
    > printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */


    Ooh, good catch!

    Assuming it appears in a valid context (within a function, and with a
    "#include <stdio.h>" in the right place), a strict reading of the
    standard could lead to the conclusion that it's undefined behavior.
    However, I think it's clear that it's not *intended* to be undefined
    behavior, and the standard can (and IMHO should) be read so that it
    isn't. (The output is implementation-defined, of course, but that's
    not what your asking about.)

    C99 7.1.4, "Use of library functions", says:

    Each of the following statements applies unless explicitly stated
    otherwise in the detailed descriptions that follow: If an argument
    to a function has an invalid value (such as a value outside the
    domain of the function, or a pointer outside the address space of
    the program, or a null pointer, or a pointer to non-modifiable
    storage when the corresponding parameter is not const-qualified)
    or a type (after promotion) not expected by a function with
    variable number of arguments, the behavior is undefined.

    C99 7.19.6.1p8, "The fprintf function" (page 279) says:

    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.

    Since this doesn't explicitly say that a null pointer is allowed, one
    could argue that it's undefined behavior.

    The escape clause, I think is that 7.1.4 says "If an argument to a
    function has an invalid value (*such as* ... a null pointer ...)". If
    I turn my head to one side and squint, I can read this as saying that
    a null pointer can be an invalid value, not necessarily that it always
    is one.

    On the other hand, the same reasoning could imply that strlen(NULL)
    doesn't invoke undefined behavior. We have to use common sense to
    determine that printf("%p\n", (void*)0)) is ok but strlen(NULL) is not
    -- but some people's "common sense" will lead them to conclude that
    the latter should always return 0.

    Realistically, any implementation won't do anything more exotic that
    printing some implementation-defined character string.

    Still, I think this calls for a DR.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Mar 6, 2005
    #5
  6. infobahn

    aegis Guest

    Keith Thompson wrote:
    > infobahn <> writes:
    > > printf("%p\n", (void *)0); /* UB, or not? Please explain your

    answer. */
    >
    > Ooh, good catch!
    >
    > Assuming it appears in a valid context (within a function, and with a
    > "#include <stdio.h>" in the right place), a strict reading of the
    > standard could lead to the conclusion that it's undefined behavior.
    > However, I think it's clear that it's not *intended* to be undefined
    > behavior, and the standard can (and IMHO should) be read so that it
    > isn't. (The output is implementation-defined, of course, but that's
    > not what your asking about.)
    >
    > C99 7.1.4, "Use of library functions", says:
    >
    > Each of the following statements applies unless explicitly stated
    > otherwise in the detailed descriptions that follow: If an

    argument
    > to a function has an invalid value (such as a value outside the
    > domain of the function, or a pointer outside the address space of
    > the program, or a null pointer, or a pointer to non-modifiable
    > storage when the corresponding parameter is not const-qualified)
    > or a type (after promotion) not expected by a function with
    > variable number of arguments, the behavior is undefined.
    >
    > C99 7.19.6.1p8, "The fprintf function" (page 279) says:
    >
    > 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.
    >
    > Since this doesn't explicitly say that a null pointer is allowed, one
    > could argue that it's undefined behavior.
    >


    Is (void *)0 a null pointer? I thought it was a null pointer constant.

    > The escape clause, I think is that 7.1.4 says "If an argument to a
    > function has an invalid value (*such as* ... a null pointer ...)".

    If
    > I turn my head to one side and squint, I can read this as saying that
    > a null pointer can be an invalid value, not necessarily that it

    always
    > is one.


    Yes. I think so too. But the example involves a null pointer constant.

    >
    > On the other hand, the same reasoning could imply that strlen(NULL)
    > doesn't invoke undefined behavior. We have to use common sense to


    strlen expects a valid string. NULL is no such thing.

    > determine that printf("%p\n", (void*)0)) is ok but strlen(NULL) is

    not
    > -- but some people's "common sense" will lead them to conclude that
    > the latter should always return 0.


    No. Because a null pointer constant is different from a null pointer.

    char *p = NULL;

    'p' is a null pointer.

    But (void *)0 is a null pointer constant in the example above.


    >
    > Realistically, any implementation won't do anything more exotic that
    > printing some implementation-defined character string.
    >
    > Still, I think this calls for a DR.
    >


    I don't.

    > --
    > Keith Thompson (The_Other_Keith)

    <http://www.ghoti.net/~kst>
    > San Diego Supercomputer Center <*>

    <http://users.sdsc.edu/~kst>
    > We must do something. This is something. Therefore, we must do

    this.

    --
    aegis
     
    aegis, Mar 6, 2005
    #6
  7. > infobahn <> writes:
    > > printf("%p\n", (void *)0); /* UB, or not? Please explain your

    answer. */

    What is _your_ theory? In other words, what leads you to question this
    in the first place?

    Keith Thompson wrote:
    > Ooh, good catch!
    >
    > Assuming it appears in a valid context (within a function, and with a
    > "#include <stdio.h>" in the right place), a strict reading of the
    > standard could lead to the conclusion that it's undefined behavior.


    Why?

    > C99 7.1.4, "Use of library functions", says:
    >
    > Each of the following statements applies unless explicitly stated
    > otherwise in the detailed descriptions that follow: If an

    argument
    > to a function has an invalid value (such as a value outside the
    > domain of the function, or a pointer outside the address space of
    > the program, or a null pointer, or a pointer to non-modifiable
    > storage when the corresponding parameter is not const-qualified)
    > or a type (after promotion) not expected by a function with
    > variable number of arguments, the behavior is undefined.
    >
    > C99 7.19.6.1p8, "The fprintf function" (page 279) says:
    >
    > 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.
    >
    > Since this doesn't explicitly say that a null pointer is allowed, one
    > could argue that it's undefined behavior.


    Since when was a pointer not allowed to be a null pointer in it's own
    right?

    > The escape clause, I think is that 7.1.4 says "If an argument to a
    > function has an invalid value (*such as* ... a null pointer ...)".

    If
    > I turn my head to one side and squint, I can read this as saying that
    > a null pointer can be an invalid value, not necessarily that it

    always
    > is one.
    >
    > On the other hand, the same reasoning could imply that strlen(NULL)
    > doesn't invoke undefined behavior.


    Since strlen 'computes the length of _a string_', it's clear that a
    null pointer is invalid.

    > Still, I think this calls for a DR.


    I say nay. ;)

    --
    Peter
     
    Peter Nilsson, Mar 6, 2005
    #7
  8. aegis wrote:
    >
    > Is (void *)0 a null pointer? I thought it was a null pointer

    constant.

    It's both, by definition.

    --
    Peter
     
    Peter Nilsson, Mar 6, 2005
    #8
  9. CBFalconer wrote:
    > infobahn wrote:
    > >
    > > printf("%p\n", (void *)0); /* UB, or not? Please explain your

    answer. */
    >
    > UB, due to lack of prototype for printf, and appearing outside of
    > the body of a function.


    I'm not convinced there's anything worth discussing in the OP's post,
    but your reply is "...100% correct and 0% helpful."

    --
    Peter
     
    Peter Nilsson, Mar 6, 2005
    #9
  10. infobahn

    infobahn Guest

    [I haven't seen Keith's reply to my original question, except in
    this reply-to-reply.]

    aegis wrote:
    >
    > Keith Thompson wrote:
    > > infobahn <> writes:
    > > > printf("%p\n", (void *)0); /* UB, or not? Please explain your

    > answer. */
    > >
    > > Ooh, good catch!
    > >
    > > Assuming it appears in a valid context (within a function, and with a
    > > "#include <stdio.h>" in the right place), a strict reading of the
    > > standard could lead to the conclusion that it's undefined behavior.


    That's part of what worries me.

    > > However, I think it's clear that it's not *intended* to be undefined
    > > behavior, and the standard can (and IMHO should) be read so that it
    > > isn't.


    And that's the rest of what worries me.


    > > (The output is implementation-defined, of course, but that's
    > > not what your asking about.)


    Correct.

    > > C99 7.1.4, "Use of library functions", says:


    Yes, that's part of my concern.

    > > C99 7.19.6.1p8, "The fprintf function" (page 279) says:


    And that's the other part.

    > Is (void *)0 a null pointer? I thought it was a null pointer constant.


    If it worries you, pretend I said:

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

    > > The escape clause, I think is that 7.1.4 says "If an argument to a
    > > function has an invalid value (*such as* ... a null pointer ...)".
    > > If I turn my head to one side and squint, I can read this as saying
    > > that a null pointer can be an invalid value, not necessarily that
    > > it always is one.


    The problem I have with this rationalisation is that it sounds too
    much like rationalisation. I can hear Herbert Schildt saying "It
    doesn't say you can't!", and that worries me.

    > > Realistically, any implementation won't do anything more exotic that
    > > printing some implementation-defined character string.
    > >
    > > Still, I think this calls for a DR.


    Or at least a clarification from the Great Powers, complete with C&V.
     
    infobahn, Mar 6, 2005
    #10
  11. "aegis" <> writes:
    > Keith Thompson wrote:
    >> infobahn <> writes:
    >> > printf("%p\n", (void *)0); /* UB, or not? Please explain your

    > answer. */

    [snip]

    > Is (void *)0 a null pointer? I thought it was a null pointer constant.


    Yes, it's a null pointer constant, which is a source construct. A
    null pointer is a value that exists at run time. In the function call
    above, a null pointer is passed as an argument to printf. (That's
    what null pointer constants are for, after all.)

    >> The escape clause, I think is that 7.1.4 says "If an argument to a
    >> function has an invalid value (*such as* ... a null pointer
    >> ...)". If I turn my head to one side and squint, I can read this as
    >> saying that a null pointer can be an invalid value, not necessarily
    >> that it always is one.

    >
    > Yes. I think so too. But the example involves a null pointer constant.


    Which results in a null pointer at run time.

    >> On the other hand, the same reasoning could imply that strlen(NULL)
    >> doesn't invoke undefined behavior. We have to use common sense to

    >
    > strlen expects a valid string. NULL is no such thing.


    One could argue that printf("%p", ...) expects a valid pointer, and
    that NULL is not a valid pointer. The wording of the standard doesn't
    exclude that interpretation.

    >> determine that printf("%p\n", (void*)0)) is ok but strlen(NULL) is

    > not
    >> -- but some people's "common sense" will lead them to conclude that
    >> the latter should always return 0.

    >
    > No. Because a null pointer constant is different from a null pointer.


    That has nothing to do with it.

    [snip]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Mar 6, 2005
    #11
  12. infobahn <> writes:
    > [I haven't seen Keith's reply to my original question, except in
    > this reply-to-reply.]


    Perhaps because aegis cross-posted his reply to comp.lang.c and
    comp.std.c (the original article was posted only to comp.lang.c).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Mar 6, 2005
    #12
  13. infobahn

    infobahn Guest

    Peter Nilsson wrote:
    >
    > CBFalconer wrote:
    > > infobahn wrote:
    > > >
    > > > printf("%p\n", (void *)0); /* UB, or not? Please explain your

    > answer. */
    > >
    > > UB, due to lack of prototype for printf, and appearing outside of
    > > the body of a function.


    (Cute.)

    >
    > I'm not convinced there's anything worth discussing in the OP's post,


    The point is this: I have written a routine which takes T **p,
    frees the memory pointed to by *p, and sets *p to NULL. In a
    demo driver routine, I am trying to show that the pointer is now
    NULL, using printf. When gcc showed me "(nil)" instead of something
    more - well - more pointery!, I was reminded of the way it responds
    to a %s/NULL match, and this concerned me, since I know perfectly
    well that %s/NULL is undefined, so I was naturally concerned to
    know whether %p/NULL is undefined too. It may be that the goal of
    avoiding undefined behaviour is not worth discussing in comp.lang.c
    but, if that is the case, why do we spend so much time discussing
    precisely that? :)

    > but [CBFalconer's] reply is "...100% correct and 0% helpful."


    Indeed. I haven't seen his reply except as quoted by your own, but
    it seems a rather strange reply to make. I expected better of him.
     
    infobahn, Mar 6, 2005
    #13
  14. > Keith Thompson wrote:

    >> The escape clause, I think is that 7.1.4 says "If an argument to a
    >> function has an invalid value (*such as* ... a null pointer ...)".
    >> If I turn my head to one side and squint, I can read this as saying
    >> that a null pointer can be an invalid value, not necessarily that
    >> it always is one.


    "such as" introduces examples, not definitions. I think your 'escape
    clause' is the natural reading.

    --
    http://www.greenend.org.uk/rjk/
     
    Richard Kettlewell, Mar 6, 2005
    #14
  15. infobahn

    pete Guest

    Keith Thompson wrote:

    > One could argue that printf("%p", ...) expects a valid pointer, and
    > that NULL is not a valid pointer. The wording of the standard doesn't
    > exclude that interpretation.


    Whether or not NULL is an invalid pointer, depends on context.
    free(NULL) is defined.
    You can't just say that NULL is an invalid pointer,
    without saying invalid for what purpose.
    An indeterminate pointer, on the other hand, is just an invalid pointer.

    --
    pete
     
    pete, Mar 6, 2005
    #15
  16. infobahn

    CBFalconer Guest

    infobahn wrote:
    > Peter Nilsson wrote:
    >> CBFalconer wrote:
    >>> infobahn wrote:
    >>>>
    >>>> printf("%p\n", (void *)0); /* UB, or not? Please explain your
    >>>> answer. */
    >>>
    >>> UB, due to lack of prototype for printf, and appearing outside of
    >>> the body of a function.

    >
    > (Cute.)
    >
    >>
    >> I'm not convinced there's anything worth discussing in the OP's post,

    >
    > The point is this: I have written a routine which takes T **p,
    > frees the memory pointed to by *p, and sets *p to NULL. In a
    > demo driver routine, I am trying to show that the pointer is now
    > NULL, using printf. When gcc showed me "(nil)" instead of something
    > more - well - more pointery!, I was reminded of the way it responds
    > to a %s/NULL match, and this concerned me, since I know perfectly
    > well that %s/NULL is undefined, so I was naturally concerned to
    > know whether %p/NULL is undefined too. It may be that the goal of
    > avoiding undefined behaviour is not worth discussing in comp.lang.c
    > but, if that is the case, why do we spend so much time discussing
    > precisely that? :)
    >
    >> but [CBFalconer's] reply is "...100% correct and 0% helpful."

    >
    > Indeed. I haven't seen his reply except as quoted by your own, but
    > it seems a rather strange reply to make. I expected better of him.


    Well, I expected better of infobahn :) As far as the statement
    (assuming a proper environment for it) is concerned, printf is
    supposed to dump out a representation of a pointer value. NULL is
    a suitable value for a pointer. (void *)0 is a means of generating
    that NULL value. I see no reason for any implementor to
    distinguish it, dereference it, or to criticize its ancestry, so I
    should not expect any problems from the snippet. If the standard
    does allow problems to arise I consider that a defect in the
    standard. And "(nil)" is a representation of a NULL pointer
    value. Various gcc oriented printf packages do this in a variety
    of situations, which is probably superior to blowing up the barn
    door and releasing all the differently colored horses.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
     
    CBFalconer, Mar 6, 2005
    #16
  17. infobahn

    infobahn Guest

    CBFalconer wrote:
    >
    > As far as the statement
    > (assuming a proper environment for it) is concerned, printf is
    > supposed to dump out a representation of a pointer value. NULL is
    > a suitable value for a pointer.


    Sometimes, yes, and other times, no. Since you seem so confident that
    it's okay to pass NULL to printf when matching with %p, perhaps you
    could explain the reasons for your confidence, citing relevant C&V.
    After all, if this were as clear-cut to me as it is to you, I would
    not have bothered asking the question; I'd like to be as convinced as
    you are, but I cannot find justification in the Standard for having
    that level of conviction in the "well-definedness" of the construct.


    > If the standard
    > does allow problems to arise I consider that a defect in the
    > standard.


    You are certainly entitled to take that view, but don't forget that
    (wise!) implementors use the text of the Standard when writing their
    implementations. If the Standard allows them to assume they will not
    be passed NULL to match a %p, then all bets are off, whether that is
    a defect in the Standard or not. That is why I am concerned.

    I'd rather *know* that the behaviour is, or is not, undefined
    according to the text of the Standard, so that I can take appropriate
    precautions in my code if need be, than rely on "gut feel" as you
    seem to be suggesting.
     
    infobahn, Mar 6, 2005
    #17
  18. infobahn

    CBFalconer Guest

    infobahn wrote:
    > CBFalconer wrote:
    >>
    >> As far as the statement (assuming a proper environment for it) is
    >> concerned, printf is supposed to dump out a representation of a
    >> pointer value. NULL is a suitable value for a pointer.

    >
    > Sometimes, yes, and other times, no. Since you seem so confident that
    > it's okay to pass NULL to printf when matching with %p, perhaps you
    > could explain the reasons for your confidence, citing relevant C&V.
    > After all, if this were as clear-cut to me as it is to you, I would
    > not have bothered asking the question; I'd like to be as convinced as
    > you are, but I cannot find justification in the Standard for having
    > that level of conviction in the "well-definedness" of the construct.
    >
    >> If the standard does allow problems to arise I consider that a
    >> defect in the standard.


    I can't justify my attitude, and you are entitled to yours. I
    simply can't conceive of a sane implementor creating a difficulty
    with this.

    The clib package I use here with gcc spits out (nil) for
    'printf("%s",NULL);', and I would be extremely leery of expecting
    that to happen anywhere else. If you are worried about the %p
    operation you can always write:

    IF (p) printf("%p\n", p);
    ELSE printf("(nil)\n");

    which is what I suspect happens within your systems printf code
    whenever a pointer is expected. You just can't count on it.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
     
    CBFalconer, Mar 6, 2005
    #18
  19. pete wrote:
    > ...
    >> One could argue that printf("%p", ...) expects a valid pointer, and
    >> that NULL is not a valid pointer. The wording of the standard doesn't
    >> exclude that interpretation.

    >
    > Whether or not NULL is an invalid pointer, depends on context.
    > free(NULL) is defined.
    > You can't just say that NULL is an invalid pointer,
    > without saying invalid for what purpose.
    > An indeterminate pointer, on the other hand, is just an invalid pointer.
    > ...


    This has already been covered above. Once again, the standard says that
    null pointer arguments can be specifically allowed by the specification
    of the concrete function from the standard library. 'free' function is a
    good example of such function: its specification explicitly states that
    passing a null pointer to it is OK (does noting). The specification of
    'printf' does not say that passing null pointers to it is OK. That's
    exactly what constitutes the problem.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Mar 6, 2005
    #19
  20. infobahn

    Quentarez Guest

    On Sat, 5 Mar 2005 22:20:00 +0000 (UTC), infobahn wrote:

    > printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */


    I, personally, would not consider this to be UB.

    I don't have supreme knowledge of the standard, nor do I have any
    references to the standard to support this claim.

    I decided to take a different route, and see what the compiler does with a
    NULL pointer. I tested it on two compilers: MSVC6 and gcc 3.3.5.

    It has already been shown previous to this post that (void *)0 is indeed a
    way to get a NULL pointer, so I will refer to it as a NULL pointer from now
    on.

    From what I've learned, a pointer always points /somewhere/, even if that
    somewhere is not where you intended.

    From simply compiling and running the given code, I get the output 00000000
    on MSVC6 and (nil) on gcc.

    Next, I did this:

    int *p = NULL;

    and used my debuggers to examine the contents of p after it had been
    initialized. On MSVC6 it was 0x00000000. On gcc it was 0x0.

    %p prints out an address, and, from what I see, a NULL pointer has a valid
    address.

    Based on my observations, it seems that

    printf("%p\n", (void *)0);

    is not UB.
     
    Quentarez, Mar 6, 2005
    #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. Ollej Reemt
    Replies:
    7
    Views:
    547
    Jack Klein
    Apr 22, 2005
  2. Stig Brautaset

    `void **' revisited: void *pop(void **root)

    Stig Brautaset, Oct 25, 2003, in forum: C Programming
    Replies:
    15
    Views:
    792
    The Real OS/2 Guy
    Oct 28, 2003
  3. whatluo

    (void) printf vs printf

    whatluo, May 26, 2005, in forum: C Programming
    Replies:
    29
    Views:
    1,252
  4. Replies:
    5
    Views:
    842
    S.Tobias
    Jul 22, 2005
  5. guru
    Replies:
    8
    Views:
    286
Loading...

Share This Page