Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > printf("%p\n", (void *)0);

Reply
Thread Tools

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

 
 
Keith Thompson
Guest
Posts: n/a
 
      03-06-2005
"aegis" <(E-Mail Removed)> writes:
> Keith Thompson wrote:
>> infobahn <(E-Mail Removed)> 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.velocityreviews.com/forums/(E-Mail Removed) <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.
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      03-06-2005
infobahn <(E-Mail Removed)> 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) (E-Mail Removed) <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.
 
Reply With Quote
 
 
 
 
infobahn
Guest
Posts: n/a
 
      03-06-2005
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.
 
Reply With Quote
 
Richard Kettlewell
Guest
Posts: n/a
 
      03-06-2005
> 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/
 
Reply With Quote
 
pete
Guest
Posts: n/a
 
      03-06-2005
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
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      03-06-2005
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


 
Reply With Quote
 
infobahn
Guest
Posts: n/a
 
      03-06-2005
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.
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      03-06-2005
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

 
Reply With Quote
 
Andrey Tarasevich
Guest
Posts: n/a
 
      03-06-2005
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

 
Reply With Quote
 
Quentarez
Guest
Posts: n/a
 
      03-06-2005
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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments