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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • infobahn

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

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

    #2
    Re: printf("%p \n", (void *)0);

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

    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.

    Comment

    • Walter Roberson

      #3
      Re: printf("%p \n", (void *)0);

      In article <422A3009.D149B 087@btinternet. com>,
      infobahn <infobahn@btint ernet.com> 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

      Comment

      • CBFalconer

        #4
        Re: printf(&quot;%p \n&quot;, (void *)0);

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

        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.c om, 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

        Comment

        • Keith Thompson

          #5
          Re: printf(&quot;%p \n&quot;, (void *)0);

          infobahn <infobahn@btint ernet.com> writes:[color=blue]
          > printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */[/color]

          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_Keit h) kst-u@mib.org <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.

          Comment

          • aegis

            #6
            Re: printf(&quot;%p \n&quot;, (void *)0);


            Keith Thompson wrote:[color=blue]
            > infobahn <infobahn@btint ernet.com> writes:[color=green]
            > > printf("%p\n", (void *)0); /* UB, or not? Please explain your[/color][/color]
            answer. */[color=blue]
            >
            > 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[/color]
            argument[color=blue]
            > 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.
            >[/color]

            Is (void *)0 a null pointer? I thought it was a null pointer constant.
            [color=blue]
            > 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 ...)".[/color]
            If[color=blue]
            > 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[/color]
            always[color=blue]
            > is one.[/color]

            Yes. I think so too. But the example involves a null pointer constant.
            [color=blue]
            >
            > On the other hand, the same reasoning could imply that strlen(NULL)
            > doesn't invoke undefined behavior. We have to use common sense to[/color]

            strlen expects a valid string. NULL is no such thing.
            [color=blue]
            > determine that printf("%p\n", (void*)0)) is ok but strlen(NULL) is[/color]
            not[color=blue]
            > -- but some people's "common sense" will lead them to conclude that
            > the latter should always return 0.[/color]

            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.

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

            I don't.
            [color=blue]
            > --
            > Keith Thompson (The_Other_Keit h) kst-u@mib.org[/color]
            <http://www.ghoti.net/~kst>[color=blue]
            > San Diego Supercomputer Center <*>[/color]
            <http://users.sdsc.edu/~kst>[color=blue]
            > We must do something. This is something. Therefore, we must do[/color]
            this.

            --
            aegis

            Comment

            • Peter Nilsson

              #7
              Re: printf(&quot;%p \n&quot;, (void *)0);

              > infobahn <infobahn@btint ernet.com> writes:[color=blue][color=green]
              > > printf("%p\n", (void *)0); /* UB, or not? Please explain your[/color][/color]
              answer. */

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

              Keith Thompson wrote:[color=blue]
              > 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.[/color]

              Why?
              [color=blue]
              > 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[/color]
              argument[color=blue]
              > 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.[/color]

              Since when was a pointer not allowed to be a null pointer in it's own
              right?
              [color=blue]
              > 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 ...)".[/color]
              If[color=blue]
              > 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[/color]
              always[color=blue]
              > is one.
              >
              > On the other hand, the same reasoning could imply that strlen(NULL)
              > doesn't invoke undefined behavior.[/color]

              Since strlen 'computes the length of _a string_', it's clear that a
              null pointer is invalid.
              [color=blue]
              > Still, I think this calls for a DR.[/color]

              I say nay. ;)

              --
              Peter

              Comment

              • Peter Nilsson

                #8
                Re: printf(&quot;%p \n&quot;, (void *)0);

                aegis wrote:[color=blue]
                >
                > Is (void *)0 a null pointer? I thought it was a null pointer[/color]
                constant.

                It's both, by definition.

                --
                Peter

                Comment

                • Peter Nilsson

                  #9
                  Re: printf(&quot;%p \n&quot;, (void *)0);

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

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

                  --
                  Peter

                  Comment

                  • infobahn

                    #10
                    Re: printf(&quot;%p \n&quot;, (void *)0);

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

                    aegis wrote:[color=blue]
                    >
                    > Keith Thompson wrote:[color=green]
                    > > infobahn <infobahn@btint ernet.com> writes:[color=darkred]
                    > > > printf("%p\n", (void *)0); /* UB, or not? Please explain your[/color][/color]
                    > answer. */[color=green]
                    > >
                    > > 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.[/color][/color]

                    That's part of what worries me.
                    [color=blue][color=green]
                    > > 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.[/color][/color]

                    And that's the rest of what worries me.

                    [color=blue][color=green]
                    > > (The output is implementation-defined, of course, but that's
                    > > not what your asking about.)[/color][/color]

                    Correct.
                    [color=blue][color=green]
                    > > C99 7.1.4, "Use of library functions", says:[/color][/color]

                    Yes, that's part of my concern.
                    [color=blue][color=green]
                    > > C99 7.19.6.1p8, "The fprintf function" (page 279) says:[/color][/color]

                    And that's the other part.
                    [color=blue]
                    > Is (void *)0 a null pointer? I thought it was a null pointer constant.[/color]

                    If it worries you, pretend I said:

                    #include <stdio.h>
                    int main(void)
                    {
                    int *p = NULL;
                    printf("%p\n", (void *)p);
                    return 0;
                    }
                    [color=blue][color=green]
                    > > 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.[/color][/color]

                    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.
                    [color=blue][color=green]
                    > > Realistically, any implementation won't do anything more exotic that
                    > > printing some implementation-defined character string.
                    > >
                    > > Still, I think this calls for a DR.[/color][/color]

                    Or at least a clarification from the Great Powers, complete with C&V.

                    Comment

                    • Keith Thompson

                      #11
                      Re: printf(&quot;%p \n&quot;, (void *)0);

                      "aegis" <aegis@mad.scie ntist.com> writes:[color=blue]
                      > Keith Thompson wrote:[color=green]
                      >> infobahn <infobahn@btint ernet.com> writes:[color=darkred]
                      >> > printf("%p\n", (void *)0); /* UB, or not? Please explain your[/color][/color]
                      > answer. */[/color]
                      [snip]
                      [color=blue]
                      > Is (void *)0 a null pointer? I thought it was a null pointer constant.[/color]

                      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.)
                      [color=blue][color=green]
                      >> 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.[/color]
                      >
                      > Yes. I think so too. But the example involves a null pointer constant.[/color]

                      Which results in a null pointer at run time.
                      [color=blue][color=green]
                      >> On the other hand, the same reasoning could imply that strlen(NULL)
                      >> doesn't invoke undefined behavior. We have to use common sense to[/color]
                      >
                      > strlen expects a valid string. NULL is no such thing.[/color]

                      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.
                      [color=blue][color=green]
                      >> determine that printf("%p\n", (void*)0)) is ok but strlen(NULL) is[/color]
                      > not[color=green]
                      >> -- but some people's "common sense" will lead them to conclude that
                      >> the latter should always return 0.[/color]
                      >
                      > No. Because a null pointer constant is different from a null pointer.[/color]

                      That has nothing to do with it.

                      [snip]

                      --
                      Keith Thompson (The_Other_Keit h) kst-u@mib.org <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.

                      Comment

                      • Keith Thompson

                        #12
                        Re: printf(&quot;%p \n&quot;, (void *)0);

                        infobahn <infobahn@btint ernet.com> writes:[color=blue]
                        > [I haven't seen Keith's reply to my original question, except in
                        > this reply-to-reply.][/color]

                        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_Keit h) kst-u@mib.org <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.

                        Comment

                        • infobahn

                          #13
                          Re: printf(&quot;%p \n&quot;, (void *)0);

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

                          (Cute.)
                          [color=blue]
                          >
                          > I'm not convinced there's anything worth discussing in the OP's post,[/color]

                          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? :-)
                          [color=blue]
                          > but [CBFalconer's] reply is "...100% correct and 0% helpful."[/color]

                          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.

                          Comment

                          • pete

                            #14
                            Re: printf(&quot;%p \n&quot;, (void *)0);

                            Keith Thompson wrote:
                            [color=blue]
                            > 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.[/color]

                            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

                            Comment

                            • CBFalconer

                              #15
                              Re: printf(&quot;%p \n&quot;, (void *)0);

                              infobahn wrote:[color=blue]
                              > Peter Nilsson wrote:[color=green]
                              >> CBFalconer wrote:[color=darkred]
                              >>> 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.[/color][/color]
                              >
                              > (Cute.)
                              >[color=green]
                              >>
                              >> I'm not convinced there's anything worth discussing in the OP's post,[/color]
                              >
                              > 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? :-)
                              >[color=green]
                              >> but [CBFalconer's] reply is "...100% correct and 0% helpful."[/color]
                              >
                              > 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.[/color]

                              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.c om, 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


                              Comment

                              Working...