I
infobahn
printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */
*/infobahn said:printf("%p\n", (void *)0); /* UB, or not? Please explain your answer.
infobahn said:printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */
infobahn said:printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */
Keith said: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.
San Diego Supercomputer Center <*>
this.We must do something. This is something. Therefore, we must do
Keith said: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.
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.
Still, I think this calls for a DR.
constant.aegis said:Is (void *)0 a null pointer? I thought it was a null pointer
CBFalconer said:answer. */
UB, due to lack of prototype for printf, and appearing outside of
the body of a function.
Correct.
Is (void *)0 a null pointer? I thought it was a null pointer constant.
aegis said:answer. */ [snip]
Is (void *)0 a null pointer? I thought it was a null pointer constant.
Yes. I think so too. But the example involves a null pointer constant.
strlen expects a valid string. NULL is no such thing.
No. Because a null pointer constant is different from a null pointer.
infobahn said:[I haven't seen Keith's reply to my original question, except in
this reply-to-reply.]
Peter said:(Cute.)
I'm not convinced there's anything worth discussing in the OP's post,
but [CBFalconer's] reply is "...100% correct and 0% helpful."
Keith said: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.
infobahn said:Peter said:(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.
CBFalconer said: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.
If the standard
does allow problems to arise I consider that a defect in the
standard.
infobahn said: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.
pete said:...
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.
...
printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.