By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,587 Members | 1,168 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,587 IT Pros & Developers. It's quick & easy.

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

P: n/a
printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */
Nov 14 '05 #1
Share this Question
Share on Google+
188 Replies


P: n/a
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.

Nov 14 '05 #2

P: n/a
In article <42***************@btinternet.com>,
infobahn <in******@btinternet.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
Nov 14 '05 #3

P: n/a
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

Nov 14 '05 #4

P: n/a
infobahn <in******@btinternet.com> 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) ks***@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.
Nov 14 '05 #5

P: n/a

Keith Thompson wrote:
infobahn <in******@btinternet.com> 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) ks***@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.

--
aegis

Nov 14 '05 #6

P: n/a
> infobahn <in******@btinternet.com> 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

Nov 14 '05 #7

P: n/a
aegis wrote:

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

constant.

It's both, by definition.

--
Peter

Nov 14 '05 #8

P: n/a
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

Nov 14 '05 #9

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

aegis wrote:

Keith Thompson wrote:
infobahn <in******@btinternet.com> 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.
Nov 14 '05 #10

P: n/a
"aegis" <ae***@mad.scientist.com> writes:
Keith Thompson wrote:
infobahn <in******@btinternet.com> 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) ks***@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.
Nov 14 '05 #11

P: n/a
infobahn <in******@btinternet.com> 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) ks***@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.
Nov 14 '05 #12

P: n/a
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.
Nov 14 '05 #13

P: n/a
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
Nov 14 '05 #14

P: n/a
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
Nov 14 '05 #15

P: n/a
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.
Nov 14 '05 #16

P: n/a
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

Nov 14 '05 #17

P: n/a
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

Nov 14 '05 #18

P: n/a
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.
Nov 14 '05 #19

P: n/a
Andrey Tarasevich wrote:
.... snip ...
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.


However the standard does say that dereferencing NULL is bad, and
that is exactly what is required for all usages of NULL in printf
except the %p descriptor. It is that omission that is giving some
people qualms.

--
"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
Nov 14 '05 #20

P: n/a
Quentarez <qu*******@cognitiveprocess.com> writes:
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.


Observing the behavior of any number of implementations doesn't
demonstrate that the behavior is defined. Undefined behavior is
exactly that, undefined. Specifically, it's

behavior, upon use of a nonportable or erroneous program construct
or of erroneous data, for which this International Standard
imposes no requirements

(C99 3.4.3p1)

Even assuming that it's UB, the behaviors of MSVC6 and gcc are
entirely consistent with the standard. (*Any* behavior would be
entirely consistent with the standard.)

The only way to determine whether a given construct invokes undefined
behavior is by a careful reading of the standard.
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.
It's better to refer to this as a "null pointer", not a "NULL
pointer". NULL is a macro that expands to a null pointer constant;
using all-caps NULL for anything else is misleading.
From what I've learned, a pointer always points /somewhere/, even if that
somewhere is not where you intended.
Not necessarily. As far as the language is concerned a null pointer
points nowhere. (It might happen to point to some location in
physical or virtual memory, but no program can determine that without
invoking undefined behavior.)

More concretely, on a system with 128 megabytes of virtual memory, a
pointer with the value 0x10000000 (that's 256 megabytes) doesn't point
anywhere -- or maybe it points to a memory card you haven't installed
yet. (For the sake of this example, I'm making several assumptions
about pointers that are commonly true, but are not required by the
standard.)
From simply compiling and running the given code, I get the output 00000000
on MSVC6 and (nil) on gcc.
Using gcc on three different platforms, I get "0x0", "0", and "(nil)".
It's the runtime library, not the compiler, that implements printf.
(As far as the standard is concerned, the compiler and the library are
both part of the implementation; in other words, "gcc" is not a
complete description of the implementation.)

[snip]
Based on my observations, it seems that

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

is not UB.


Based on your observations, it could very well be UB.

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #21

P: n/a
CBFalconer <cb********@yahoo.com> writes:
Andrey Tarasevich wrote:

... snip ...

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.


However the standard does say that dereferencing NULL is bad, and
that is exactly what is required for all usages of NULL in printf
except the %p descriptor. It is that omission that is giving some
people qualms.


For that matter, a printf implementation *could* attempt to
dereference the pointer associated with the "%p" descriptor (after an
appropriate conversion, of course). It might be useful for the "%p"
output to show both the value of the pointer and, say, the first few
bytes of the memory it points to. "The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner."

In my opinion such an implementation that blew up attempting to
dereference a null pointer would be less than useful, and would
violate what I presume to be the intent of the standard, but the
actual wording of the standard doesn't quite forbid it.

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #22

P: n/a
On Sun, 06 Mar 2005 20:48:01 GMT, Keith Thompson wrote:
Quentarez <qu*******@cognitiveprocess.com> writes:
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.


Observing the behavior of any number of implementations doesn't
demonstrate that the behavior is defined. Undefined behavior is
exactly that, undefined. Specifically, it's

behavior, upon use of a nonportable or erroneous program construct
or of erroneous data, for which this International Standard
imposes no requirements

(C99 3.4.3p1)

Even assuming that it's UB, the behaviors of MSVC6 and gcc are
entirely consistent with the standard. (*Any* behavior would be
entirely consistent with the standard.)

The only way to determine whether a given construct invokes undefined
behavior is by a careful reading of the standard.
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.


It's better to refer to this as a "null pointer", not a "NULL
pointer". NULL is a macro that expands to a null pointer constant;
using all-caps NULL for anything else is misleading.
From what I've learned, a pointer always points /somewhere/, even if that
somewhere is not where you intended.


Not necessarily. As far as the language is concerned a null pointer
points nowhere. (It might happen to point to some location in
physical or virtual memory, but no program can determine that without
invoking undefined behavior.)

More concretely, on a system with 128 megabytes of virtual memory, a
pointer with the value 0x10000000 (that's 256 megabytes) doesn't point
anywhere -- or maybe it points to a memory card you haven't installed
yet. (For the sake of this example, I'm making several assumptions
about pointers that are commonly true, but are not required by the
standard.)
From simply compiling and running the given code, I get the output 00000000
on MSVC6 and (nil) on gcc.


Using gcc on three different platforms, I get "0x0", "0", and "(nil)".
It's the runtime library, not the compiler, that implements printf.
(As far as the standard is concerned, the compiler and the library are
both part of the implementation; in other words, "gcc" is not a
complete description of the implementation.)

[snip]
Based on my observations, it seems that

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

is not UB.


Based on your observations, it could very well be UB.


Ah! My definition of UB was completely incorrect. Thank you very much for
your response and clarification! :)
Nov 14 '05 #23

P: n/a

Keith Thompson wrote:
Quentarez <qu*******@cognitiveprocess.com> writes:
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.
Observing the behavior of any number of implementations doesn't
demonstrate that the behavior is defined. Undefined behavior is
exactly that, undefined. Specifically, it's

behavior, upon use of a nonportable or erroneous program

construct or of erroneous data, for which this International Standard
imposes no requirements

(C99 3.4.3p1)

Even assuming that it's UB, the behaviors of MSVC6 and gcc are
entirely consistent with the standard. (*Any* behavior would be
entirely consistent with the standard.)

The only way to determine whether a given construct invokes undefined
behavior is by a careful reading of the standard.
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.


It's better to refer to this as a "null pointer", not a "NULL
pointer". NULL is a macro that expands to a null pointer constant;
using all-caps NULL for anything else is misleading.
From what I've learned, a pointer always points /somewhere/, even if that somewhere is not where you intended.


Not necessarily. As far as the language is concerned a null pointer
points nowhere. (It might happen to point to some location in
physical or virtual memory, but no program can determine that without
invoking undefined behavior.)


It does point somewhere. It points to no object. And 'no object' does
not
mean 'nowhere'.

--
aegis

Nov 14 '05 #24

P: n/a
On 2005-03-06 20:56, Keith Thompson wrote:
:
For that matter, a printf implementation *could* attempt to
dereference the pointer associated with the "%p" descriptor (after an
appropriate conversion, of course). It might be useful for the "%p"
output to show both the value of the pointer and, say, the first few
bytes of the memory it points to. "The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner."


The first few bytes of memory it points to is not part of the value
of the pointer, though (well, unless it points to itself...).
Arguably, converting "the value of the pointer" should never require
dereferencing the value.

-- Niklas Matthies
Nov 14 '05 #25

P: n/a
Niklas Matthies <us***********@nmhq.net> writes:
On 2005-03-06 20:56, Keith Thompson wrote:
:
For that matter, a printf implementation *could* attempt to
dereference the pointer associated with the "%p" descriptor (after an
appropriate conversion, of course). It might be useful for the "%p"
output to show both the value of the pointer and, say, the first few
bytes of the memory it points to. "The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner."


The first few bytes of memory it points to is not part of the value
of the pointer, though (well, unless it points to itself...).
Arguably, converting "the value of the pointer" should never require
dereferencing the value.


That's a good point. My thought is that the phrase "in an
implementation-defined manner" might leave enough leeway to look at
what it points to (and it could actually be useful). But since it's a
void*, it's hard to decide how many bytes to display.

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #26

P: n/a
Keith Thompson wrote:
Niklas Matthies <us***********@nmhq.net> writes:
On 2005-03-06 20:56, Keith Thompson wrote:
For that matter, a printf implementation *could* attempt to
dereference the pointer associated with the "%p" descriptor
(after an appropriate conversion, of course).
And printing an integer could cause that integer to be converted
to a pointer and subsequently dereferenced. The standard doesn't
seem to preclude it, so it must be an option, right? ;)
It might be useful for the "%p" output to show both the value
of the pointer and, say, the first few bytes of the memory it
points to.
Your use of the word 'both' implies you already recognise the
distinction.
"The value of the pointer is converted to a sequence of
printing characters, in an implementation-defined manner."


The first few bytes of memory it points to is not part of the
value of the pointer, though (well, unless it points to
itself...). Arguably, converting "the value of the pointer"
should never require dereferencing the value.


That's a good point. My thought is that the phrase "in an
implementation-defined manner" might leave enough leeway to
look at what it points to...


Think about these...

char a[42];
printf("%p\n", a + 42);

char *p = malloc(0);
printf("%p\n", p);

More pragmatically, consider a conforming implementation
that allows pointers to be generated for all sorts of things,
including memory mapped I/O. Such an implementation would have
to check the pointer _very carefully_ to determine that
subsequent dereferencing will not reformat the harddisk!

--
Peter

Nov 14 '05 #27

P: n/a
"aegis" <ae***@mad.scientist.com> writes:
Keith Thompson wrote:
Quentarez <qu*******@cognitiveprocess.com> writes: [...]
> From what I've learned, a pointer always points /somewhere/, even
> if that somewhere is not where you intended.


Not necessarily. As far as the language is concerned a null pointer
points nowhere. (It might happen to point to some location in
physical or virtual memory, but no program can determine that without
invoking undefined behavior.)


It does point somewhere. It points to no object. And 'no object'
does not mean 'nowhere'.


Yes, it does. There isn't some mythical object called "no object".
"It points to no object" means the same as "It doesn't point to an
object".

To use a physical analogy, suppose I have a laser pointer that I can
use to point to various objects. If I aim it at an empty spot in the
sky, it's still pointing, but it's not pointing to any object. If I
turn it off, it's not pointing.

A null pointer is like a laser pointer that's turned off.

If you view it as a raw machine-level address (physical or virtual,
whichever is used for C pointers), a null pointer *might* happen to be
the address of some actual chunk of memory, or it might contain a
virtual address that's not mapped into the current process's address
space or a physical address that doesn't correspond to any real
memory. The C standard doesn't distinguish between these cases; as
far as C is concerned, a null pointer doesn't point. No program can
determine whether a null pointer acts as if it pointed to something
without invoking undefined behavior.

What the C standard says is that it "is guaranteed to compare unequal
to a pointer to any object or function"; it also says that applying
the unary "*" operator to an invalid pointer (including a null
pointer) invokes undefined behavior.

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #28

P: n/a
Keith Thompson <ks***@mib.org> writes:
For that matter, a printf implementation *could* attempt to
dereference the pointer associated with the "%p" descriptor (after an
appropriate conversion, of course). It might be useful for the "%p"
output to show both the value of the pointer and, say, the first few
bytes of the memory it points to.


That would make the following impossible to implement portably
without invoking undefined behavior, whereas I don't think it
should be:
printf("%p\n", malloc(0));
A real implementation would probably have extra knowledge though.
--
"Some people *are* arrogant, and others read the FAQ."
--Chris Dollin
Nov 14 '05 #29

P: n/a

Keith Thompson wrote:
"aegis" <ae***@mad.scientist.com> writes:
Keith Thompson wrote:
Quentarez <qu*******@cognitiveprocess.com> writes: [...] > From what I've learned, a pointer always points /somewhere/, even > if that somewhere is not where you intended.

Not necessarily. As far as the language is concerned a null pointer points nowhere. (It might happen to point to some location in
physical or virtual memory, but no program can determine that without invoking undefined behavior.)


It does point somewhere. It points to no object. And 'no object'
does not mean 'nowhere'.


Yes, it does. There isn't some mythical object called "no object".
"It points to no object" means the same as "It doesn't point to an
object".


Noone said it is mythical. The standard clearly states that
the purpose of a null pointer is to distinguish between
pointing to an object and no object. You can think of it as having
a set of objects with one object for representing no object.
Let's call the special object the sentinel.
When our pointer points to the sentinel, it means 'no object'.
When our pointer is not pointing to the sentinel, it is pointing
to an object(except where the value is invalid). In either case,
our pointer points to something but is never 'turned off' since
it is always functioning. That is the point of pointers, you see?
To point to things. If the pointer were to be 'turned off' it would
stop functioning, in which case we would be unable to determine
if it points to the object that represents no object. ;-)

--
aegis

Nov 14 '05 #30

P: n/a
aegis wrote:
Keith Thompson wrote:
"aegis" <ae***@mad.scientist.com> writes:
Keith Thompson wrote:
> As far as the language is concerned a null pointer points
> nowhere. (It might happen to point to some location in
> physical or virtual memory, but no program can determine
> that without invoking undefined behavior.)

It does point somewhere. It points to no object. And 'no
object' does not mean 'nowhere'.
Yes, it does. There isn't some mythical object called "no
object". "It points to no object" means the same as "It
doesn't point to an object".


Noone said it is mythical. The standard clearly states that
the purpose of a null pointer is to distinguish between
pointing to an object and no object.


What it clearly says is "If a null pointer constant is converted
to a pointer type, the resulting pointer, called a null pointer,
is guaranteed to compare unequal to a pointer to any object or
function."

Keith's point is that there is no requirement that a null pointer
actually point to a valid address location.

Consider a cpu with 24-bit address space, but 32-bit address/data
registers. Such a machine may have 255 or more null pointer
representations, none of which point to a genuine addressable
memory location.
You can think of it as having a set of objects with one object
for representing no object.
That is one possible method, and indeed it is the most common
one. Address 0 (all bits zero), is typically used since it either
points to unused low memory, or possibly header stuff at the
beginning of a text/data/etc... segment.
Let's call the special object the sentinel.


You're talking in terms of objects. This is misleading since the
standard clearly defines what is and what isn't an object. It
makes no sense within the C context to describe null pointers
as pointing to an object, even if that object is never 'used'.

The only thing the standard requires is that there is at least
one null pointer _representation_. Whatever that (or those)
representations are is not specified by the C standards. They
are not required to be valid physical or virtual addresses.
They may even be technical 'trap' representations within the
machine, i.e. addresses which, if the contents are fetched,
will raise a bus interupt, but which can otherwise be compared
safely.

--
Peter

Nov 14 '05 #31

P: n/a

Peter Nilsson wrote:
aegis wrote:
Keith Thompson wrote:
"aegis" <ae***@mad.scientist.com> writes:
> Keith Thompson wrote:
> > As far as the language is concerned a null pointer points
> > nowhere. (It might happen to point to some location in
> > physical or virtual memory, but no program can determine
> > that without invoking undefined behavior.)
>
> It does point somewhere. It points to no object. And 'no
> object' does not mean 'nowhere'.

Yes, it does. There isn't some mythical object called "no
object". "It points to no object" means the same as "It
doesn't point to an object".
Noone said it is mythical. The standard clearly states that
the purpose of a null pointer is to distinguish between
pointing to an object and no object.


What it clearly says is "If a null pointer constant is converted
to a pointer type, the resulting pointer, called a null pointer,
is guaranteed to compare unequal to a pointer to any object or
function."

Keith's point is that there is no requirement that a null pointer
actually point to a valid address location.


That isn't even being disputed. And if that is what he
was trying to get across then he is horribly confused.

I just pointed out that saying pointing to 'no object' is not
the same as pointing 'nowhere'.
Consider a cpu with 24-bit address space, but 32-bit address/data
registers. Such a machine may have 255 or more null pointer
representations, none of which point to a genuine addressable
memory location.


I don't see how this is relevant.
You can think of it as having a set of objects with one object
for representing no object.


That is one possible method, and indeed it is the most common
one. Address 0 (all bits zero), is typically used since it either
points to unused low memory, or possibly header stuff at the
beginning of a text/data/etc... segment.


I don't see why you are introducing these irrelevant
details. Again, I was pointing out that pointing to
'no object' does not mean 'pointing to nowhere'.
Let's call the special object the sentinel.


You're talking in terms of objects. This is misleading since the
standard clearly defines what is and what isn't an object. It
makes no sense within the C context to describe null pointers
as pointing to an object, even if that object is never 'used'.


The point of that was to aid in distinguishing the object
that represents 'no object'.

And I did so in an abstract way to show that thinking
a null pointer points to 'nowhere' is nonsense.

--
aegis

Nov 14 '05 #32

P: n/a
Keith Thompson wrote:

CBFalconer <cb********@yahoo.com> writes:
Andrey Tarasevich wrote:

... snip ...

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.


However the standard does say that dereferencing NULL is bad, and
that is exactly what is required for all usages of NULL in printf
except the %p descriptor. It is that omission that is giving some
people qualms.


For that matter, a printf implementation *could* attempt to
dereference the pointer associated with the "%p" descriptor (after an
appropriate conversion, of course). It might be useful for the "%p"
output to show both the value of the pointer and, say, the first few
bytes of the memory it points to. "The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner."

In my opinion such an implementation that blew up attempting to
dereference a null pointer would be less than useful, and would
violate what I presume to be the intent of the standard, but the
actual wording of the standard doesn't quite forbid it.


How about printing the value of the one past pointer,
do you think that is undefined?

/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
unsigned char a;

printf("&a + 1 is %p.\n", (void *)(&a + 1));
return 0;
}

/* END new.c */
--
pete
Nov 14 '05 #33

P: n/a
aegis wrote:

Peter Nilsson wrote:
aegis wrote:

Let's call the special object the sentinel.


You're talking in terms of objects. This is misleading since the
standard clearly defines what is and what isn't an object. It
makes no sense within the C context to describe null pointers
as pointing to an object, even if that object is never 'used'.


The point of that was to aid in distinguishing the object
that represents 'no object'.


But there isn't an object that represents 'no object'. If there were
such an object, a null pointer would not be allowed to point to it,
since null pointers don't point to any object, not even a 'no object'
object.
Nov 14 '05 #34

P: n/a

infobahn wrote:
aegis wrote:

Peter Nilsson wrote:
aegis wrote:

> Let's call the special object the sentinel.

You're talking in terms of objects. This is misleading since the
standard clearly defines what is and what isn't an object. It
makes no sense within the C context to describe null pointers
as pointing to an object, even if that object is never 'used'.


The point of that was to aid in distinguishing the object
that represents 'no object'.


But there isn't an object that represents 'no object'. If there were
such an object, a null pointer would not be allowed to point to it,
since null pointers don't point to any object, not even a 'no object'
object.


You are confusing things here. The set of objects
is an abstract notion. Don't confuse it with something
conrete. That being said, don't think of the 'object'
that represents no object, as a region of storage in
the execution environment. I thought that was obvious
given that I was talking in terms of sets. You could
subtitute the use of 'object' there with 'entity' and
produce the same meaning. This would then read as:

the 'entity' that represents 'no object'.

Which, in concrete terms, is what a null pointer does.

A pointer being the 'entity' and the value being the
thing that aids in making the distinction between 'object'
and 'no object'. By now, you should see that an 'entity'
points to either of the two(indeterminancy being irrelevant
to my point), but never 'nowhere'.

--
aegis

Nov 14 '05 #35

P: n/a
aegis wrote:

infobahn wrote:
aegis wrote:

Peter Nilsson wrote:
> aegis wrote:

> > Let's call the special object the sentinel.
>
> You're talking in terms of objects. This is misleading since the
> standard clearly defines what is and what isn't an object. It
> makes no sense within the C context to describe null pointers
> as pointing to an object, even if that object is never 'used'.
>

The point of that was to aid in distinguishing the object
that represents 'no object'.
But there isn't an object that represents 'no object'. If there were
such an object, a null pointer would not be allowed to point to it,
since null pointers don't point to any object, not even a 'no object'
object.


You are confusing things here.


Obviously, I disagree.
The set of objects
is an abstract notion. Don't confuse it with something
conrete.
I must disagree again.
That being said, don't think of the 'object'
that represents no object, as a region of storage in
the execution environment.
If it isn't a region of storage in the execution environment, it
can't be an object, because that's what an object *is*.
I thought that was obvious
given that I was talking in terms of sets. You could
subtitute the use of 'object' there with 'entity' and
produce the same meaning. This would then read as:

the 'entity' that represents 'no object'.
I see no justification in the Standard for assuming the existence
of such an entity. The closest I can get to it is "null pointer",
which doesn't point to any object at all.
Which, in concrete terms, is what a null pointer does.

A pointer being the 'entity' and the value being the
thing that aids in making the distinction between 'object'
and 'no object'. By now, you should see that an 'entity'
points to either of the two(indeterminancy being irrelevant
to my point), but never 'nowhere'.


This 'no-object entity' doesn't exist. It isn't anywhere. And
therefore it's nowhere. So if a null pointer points to it,
that null pointer points nowhere. And if it doesn't, the point
is moot.
Nov 14 '05 #36

P: n/a
Ben Pfaff <bl*@cs.stanford.edu> writes:
Keith Thompson <ks***@mib.org> writes:
For that matter, a printf implementation *could* attempt to
dereference the pointer associated with the "%p" descriptor (after an
appropriate conversion, of course). It might be useful for the "%p"
output to show both the value of the pointer and, say, the first few
bytes of the memory it points to.
That would make the following impossible to implement portably
without invoking undefined behavior, whereas I don't think it
should be:
printf("%p\n", malloc(0));


Much of the C library is impossible to implement portably without
invoking undefined behavior.
A real implementation would probably have extra knowledge though.


True. In any case, it was just an idle thought, probably not worth
spending too much time on.

I was trying to think of a reason why printf("%p", ptr) might invoke
undefined behavior if ptr is null -- but of course any non-stupid
implementer would check whether ptr==NULL before trying to print what,
if anything, it points to.

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #37

P: n/a

infobahn wrote:
aegis wrote:

infobahn wrote:
aegis wrote:
>
> Peter Nilsson wrote:
> > aegis wrote:
>
> > > Let's call the special object the sentinel.
> >
> > You're talking in terms of objects. This is misleading since the > > standard clearly defines what is and what isn't an object. It
> > makes no sense within the C context to describe null pointers
> > as pointing to an object, even if that object is never 'used'. > >
>
> The point of that was to aid in distinguishing the object
> that represents 'no object'.

But there isn't an object that represents 'no object'. If there were such an object, a null pointer would not be allowed to point to it, since null pointers don't point to any object, not even a 'no object' object.
You are confusing things here.


Obviously, I disagree.
The set of objects
is an abstract notion. Don't confuse it with something
conrete.


I must disagree again.
That being said, don't think of the 'object'
that represents no object, as a region of storage in
the execution environment.


If it isn't a region of storage in the execution environment, it
can't be an object, because that's what an object *is*.


'no object' is a thing, and as a thing is an object.
Like a car is an object. A bicycle is an object.
A plane is an object. Etc. See the abstraction?

I thought that was obvious
given that I was talking in terms of sets. You could
subtitute the use of 'object' there with 'entity' and
produce the same meaning. This would then read as:

the 'entity' that represents 'no object'.


I see no justification in the Standard for assuming the existence
of such an entity. The closest I can get to it is "null pointer",
which doesn't point to any object at all.


That's what I was pointing out. It points to a thing.
That thing is called 'no object'. 'no object' isn't the
same as 'nowhere'. For if a pointer were to point
to 'nowhere', we would not be able to use it in any
meaningful way(you can think of 'nowhere' as a pointer
having an indeterminate value)
Which, in concrete terms, is what a null pointer does.

A pointer being the 'entity' and the value being the
thing that aids in making the distinction between 'object'
and 'no object'. By now, you should see that an 'entity'
points to either of the two(indeterminancy being irrelevant
to my point), but never 'nowhere'.


This 'no-object entity' doesn't exist. It isn't anywhere. And
therefore it's nowhere. So if a null pointer points to it,
that null pointer points nowhere. And if it doesn't, the point
is moot.


The 'no object' is somewhere. It is at NULL. :-)

--
aegis

Nov 14 '05 #38

P: n/a
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:

[...]
For that matter, a printf implementation *could* attempt to
dereference the pointer associated with the "%p" descriptor (after an
appropriate conversion, of course). It might be useful for the "%p"
output to show both the value of the pointer and, say, the first few
bytes of the memory it points to. "The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner."

In my opinion such an implementation that blew up attempting to
dereference a null pointer would be less than useful, and would
violate what I presume to be the intent of the standard, but the
actual wording of the standard doesn't quite forbid it.


How about printing the value of the one past pointer,
do you think that is undefined?

/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
unsigned char a;

printf("&a + 1 is %p.\n", (void *)(&a + 1));
return 0;
}

/* END new.c */


That's another thing that needs to be resolved. In my opinion, the
answer *should* be no; it should be possible to pass any pointer to an
object, or just past the end of an object, or a null pointer, to
printf("%p", ...) without invoking undefined behavior.

The standard tells us that a call to a library function invokes
invokes undefined behavior if an argument has "an invalid value". For
pointers, though, validity depends on the context in which it's used;
a pointer that's valid for assignment or equality comparison may not
be valid for pointer arithmetic, a pointer that's valid for arithmetic
may not be valid for dereferencing, and a pointer that's valid as a
pointer to one type may be invalid as a pointer to another type (after
conversion). The standard needs to be clearer about which pointer
values are "valid" for printf("%p", ...).

It might even be nice to have a more expansive definition of validity
for this context than for others. For example, the standard *could*
specify that this:

void *ptr = malloc(1);
if (ptr != NULL) {
free(ptr);
printf("ptr = %p\n", ptr);
}

does not invoke undefined behavior. (printf doesn't have to treat the
value as a pointer; it could, for example, type-pun it as an array of
unsigned char to determine a hexadecimal representation.)

I don't *think* I'm seriously suggesting this. (I wonder whether it
would break any existing implementations.)

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #39

P: n/a
"Peter Nilsson" <ai***@acay.com.au> writes:
[...]
Consider a cpu with 24-bit address space, but 32-bit address/data
registers. Such a machine may have 255 or more null pointer
representations, none of which point to a genuine addressable
memory location.


Actually it could have 4278190080 such pointer representations
(2**32 - 2**24). (Whether they all be treated as C null pointers is
another question.)

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #40

P: n/a
"aegis" <ae***@mad.scientist.com> writes:
Peter Nilsson wrote: [...]
Keith's point is that there is no requirement that a null pointer
actually point to a valid address location.


That isn't even being disputed. And if that is what he
was trying to get across then he is horribly confused.


My only confusion is about what you're trying to say.
I just pointed out that saying pointing to 'no object' is not
the same as pointing 'nowhere'.


Then what's the difference? Assuming there's no valid address
location associated with a null pointer, in what sense does a null
pointer "point" anywhere?

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #41

P: n/a
"aegis" <ae***@mad.scientist.com> writes:
[...]
'no object' is a thing, and as a thing is an object.


Nonsense.

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #42

P: n/a
aegis wrote:

infobahn wrote:
aegis wrote:

That being said, don't think of the 'object'
that represents no object, as a region of storage in
the execution environment.
If it isn't a region of storage in the execution environment, it
can't be an object, because that's what an object *is*.


'no object' is a thing,


Really? I'd have thought it was 'no thing'.
and as a thing is an object.
No, in C an object is not a "thing", but a region of storage in
the execution environment.
Like a car is an object. A bicycle is an object.
A plane is an object. Etc. See the abstraction?
The abstraction is irrelevant, because the C Standard (which is what
we're on about) doesn't consider cars, bicycles, or planes to be
objects unless they are regions of storage in the execution
environment.
I thought that was obvious
given that I was talking in terms of sets. You could
subtitute the use of 'object' there with 'entity' and
produce the same meaning. This would then read as:

the 'entity' that represents 'no object'.
I see no justification in the Standard for assuming the existence
of such an entity. The closest I can get to it is "null pointer",
which doesn't point to any object at all.


That's what I was pointing out. It points to a thing.


The C Standard doesn't agree with you.
That thing is called 'no object'.


Chapter and verse, please.
Which, in concrete terms, is what a null pointer does.

A pointer being the 'entity' and the value being the
thing that aids in making the distinction between 'object'
and 'no object'. By now, you should see that an 'entity'
points to either of the two(indeterminancy being irrelevant
to my point), but never 'nowhere'.


This 'no-object entity' doesn't exist. It isn't anywhere. And
therefore it's nowhere. So if a null pointer points to it,
that null pointer points nowhere. And if it doesn't, the point
is moot.


The 'no object' is somewhere. It is at NULL. :-)


If, as you claim, the 'no object' is in fact an object, then
NULL can't point there.

"An integral constant expression with the value 0, or such an
expression cast to type void * , is called a null pointer constant. If
a null pointer constant is assigned to or compared for equality to a
pointer, the constant is converted to a pointer of that type. Such a
pointer, called a null pointer, is guaranteed to compare unequal to a
pointer to any object or function."
Nov 14 '05 #43

P: n/a

Keith Thompson wrote:
"aegis" <ae***@mad.scientist.com> writes:
Peter Nilsson wrote:

[...]
Keith's point is that there is no requirement that a null pointer
actually point to a valid address location.


That isn't even being disputed. And if that is what he
was trying to get across then he is horribly confused.


My only confusion is about what you're trying to say.
I just pointed out that saying pointing to 'no object' is not
the same as pointing 'nowhere'.


Then what's the difference? Assuming there's no valid address
location associated with a null pointer, in what sense does a null
pointer "point" anywhere?


In terms of indeterminant values, it can't be said to point anywhere
meaningful. But given that a pointer object contains NULL as a value,
it is said to 'point' to 'no object'. Which is how we distinguish
between valid objects and no objects. 0, (void *)0, NULL, etc,
represent this by a distinguishable value. What is at this address
is 'no object'. See how meaningful it is? Saying a pointer
that is a null pointer, points to nowhere, is not meaningful.
And in fact, that is an oxymoron. Because as a pointer, it will point
to something. That is the nature of a pointer. But the issue is
whether or not that something it points at, is meaningful. And yes,
Keith, 'no object' is a thing. It is a distinguishable entity crafted
by the committee so that one can differentiate between 'no object' and
'object'.

--
aegis

Nov 14 '05 #44

P: n/a

infobahn wrote:
aegis wrote:

infobahn wrote:
aegis wrote:
>
> That being said, don't think of the 'object'
> that represents no object, as a region of storage in
> the execution environment.

If it isn't a region of storage in the execution environment, it
can't be an object, because that's what an object *is*.

'no object' is a thing,


Really? I'd have thought it was 'no thing'.
and as a thing is an object.


No, in C an object is not a "thing", but a region of storage in
the execution environment.
Like a car is an object. A bicycle is an object.
A plane is an object. Etc. See the abstraction?


The abstraction is irrelevant, because the C Standard (which is what
we're on about) doesn't consider cars, bicycles, or planes to be
objects unless they are regions of storage in the execution
environment.
> I thought that was obvious
> given that I was talking in terms of sets. You could
> subtitute the use of 'object' there with 'entity' and
> produce the same meaning. This would then read as:
>
> the 'entity' that represents 'no object'.

I see no justification in the Standard for assuming the existence
of such an entity. The closest I can get to it is "null pointer",
which doesn't point to any object at all.


That's what I was pointing out. It points to a thing.


The C Standard doesn't agree with you.
That thing is called 'no object'.


Chapter and verse, please.
> Which, in concrete terms, is what a null pointer does.
>
> A pointer being the 'entity' and the value being the
> thing that aids in making the distinction between 'object'
> and 'no object'. By now, you should see that an 'entity'
> points to either of the two(indeterminancy being irrelevant
> to my point), but never 'nowhere'.

This 'no-object entity' doesn't exist. It isn't anywhere. And
therefore it's nowhere. So if a null pointer points to it,
that null pointer points nowhere. And if it doesn't, the point
is moot.


The 'no object' is somewhere. It is at NULL. :-)


If, as you claim, the 'no object' is in fact an object, then
NULL can't point there.

"An integral constant expression with the value 0, or such an
expression cast to type void * , is called a null pointer constant.

If a null pointer constant is assigned to or compared for equality to a
pointer, the constant is converted to a pointer of that type. Such a
pointer, called a null pointer, is guaranteed to compare unequal to a
pointer to any object or function."


wow, you have completely missed everything that I have said
thus far. I'm well aware of what the standard defines as
an object. And I even pointed out my other use of object
to talk about the issue in an even more abstract way.
But you have completely failed to realize this. Are you
always this obtuse?

--
aegis

Nov 14 '05 #45

P: n/a
"aegis" <ae***@mad.scientist.com> writes:
[...]
And yes, Keith, 'no object' is a thing.


What part of the word "no" do you not understand?

I have no dog. This "no dog" is not an object, it is not a thing, it
is not a dog. I simply don't have a dog. That's what "no" means.

A null pointer points to no object. That means that a null pointer
does not point to any object. There's no "there" there.

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #46

P: n/a
aegis wrote:

infobahn wrote:
aegis wrote:

The 'no object' is somewhere. It is at NULL. :-)
If, as you claim, the 'no object' is in fact an object, then
NULL can't point there.

"An integral constant expression with the value 0, or such an
expression cast to type void * , is called a null pointer constant.
If a null pointer constant is assigned to or compared for equality
to a pointer, the constant is converted to a pointer of that type.
Such a pointer, called a null pointer, is guaranteed to compare
unequal to a pointer to any object or function."


wow, you have completely missed everything that I have said
thus far.


No, I've read as much of the thread as I have received on my newsreader
pretty carefully, because I'm hoping against hope that I might receive
a useful answer to my question. But so far, what you've said doesn't
relate to what the Standard says about objects or NULL.
I'm well aware of what the standard defines as
an object. And I even pointed out my other use of object
to talk about the issue in an even more abstract way.
But you have completely failed to realize this. Are you
always this obtuse?


I realise you are trying to use the word "object" in a way that the
Standard doesn't recognise. You can use the word "object" to mean
anything you like, but as soon as you use it in a way that doesn't
coincide with the Standard's definition, your usage ceases to be
meaningful in a discussion of the behaviour required by the
Standard.
Nov 14 '05 #47

P: n/a

Keith Thompson wrote:
"aegis" <ae***@mad.scientist.com> writes:
[...]
And yes, Keith, 'no object' is a thing.


What part of the word "no" do you not understand?

I have no dog. This "no dog" is not an object, it is not a thing, it
is not a dog. I simply don't have a dog. That's what "no" means.

A null pointer points to no object. That means that a null pointer
does not point to any object. There's no "there" there.


'no object' is a thing. It is a concept. It allows us to
answer the question
'does this pointer point to an object or no object?'

--
aegis

Nov 14 '05 #48

P: n/a
aegis wrote:
Saying a pointer that is a null pointer, points to nowhere,
is not meaningful. And in fact, that is an oxymoron. Because
as a pointer, it will point to something. That is the nature
of a pointer. But the issue is whether or not that something
it points at, is meaningful. And yes, ... 'no object' is
a thing. It is a distinguishable entity crafted by the
committee so that one can differentiate between 'no object'
and 'object'.


So, NO OBJECT is a THING-IN-ITSELF?

I see now...

--
Peter

Nov 14 '05 #49

P: n/a

Keith Thompson wrote:
"aegis" <ae***@mad.scientist.com> writes:
[...]
And yes, Keith, 'no object' is a thing.


What part of the word "no" do you not understand?

I have no dog. This "no dog" is not an object, it is not a thing, it
is not a dog. I simply don't have a dog. That's what "no" means.

A null pointer points to no object. That means that a null pointer
does not point to any object. There's no "there" there.


'no object' is a thing. It is a goddamn concept. And that concept
is used to define a value that is used with pointers so that
one may get an answer to the question,
'do I point to an object or no object?'

Please engage your brain before posting next time.

--
aegis

Nov 14 '05 #50

188 Replies

This discussion thread is closed

Replies have been disabled for this discussion.