473,387 Members | 1,721 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Null pointers

Can 0x0 be a valid virtual address in the address space
of an application ?
If it is valid, then the location pointed by a NULL pointer
is also valid and application should not receive "SIGSEGV"
( i am talking of unix machine ) while trying to read that
location.
Then how can i distinguish between a NULL pointer and an invalid
location ?
Is this essential that NULL pointer should not point to any of
the location in the virtual address space ?

If NULL pointer should not essentially point to an invalid
location, then why we should always use NULL to be location 0x0,
can we use some other location as well ?

Is this necessary that whenever an application try to access
location pointed by NULL pointer, it should be aborted by kernel
by posting some signal ?

Please i need your help, beacuse i am getting more confused
as i am reading more and more documents on NULL pointers.
thanx for any help in advance.....
Nov 14 '05
102 5881
"Mabden" <mabden@sbc_global.net> writes:
[...]
Of course I get that they don't "need" to point to location zero. Do you
understand that? I gave an example where NULL was pointing to 0x12344321. I
get that. NULL or null pointer or whatever does not need to point at
location zero. See, I get it. That's not my point.
Great.
My point is that in addition to the NULL or null of whatever you want to
call the thing, separately, and different from that issue, is that location
zero in memory should not be able to store data in a C program.


You're simply wrong about this. Read the reference section (Appendix
A) of K&R2. Read the FAQ, particularly section 5. If you don't have
a copy of the actual C standard, read the relevant portions of the
latest public draft (Google "n869"). Or if you're unwilling to do
that, just listen to the rest of us, who do actually know what we're
talking about.

As you know, the null pointer may or may not be all-bits-zero. As
you've so far refused to acknowledge, the C language says nothing in
particular about an all-bits-zero address; if it's not a null pointer,
it could easily be the address of an object. The only basis for
believing otherwise is a vaguely worded (and arguably incorrect)
sentence on page 102 of K&R2.

BTW, I had forgotten until recently about my previous encounters with
you in this newsgroup. As of just a couple of months ago, you were a
deliberate, self-admitted troll. It's hard to avoid the conclusion
that you haven't changed much. Do you honestly believe that an
all-bits-zero address is somehow special, or are you just trolling
again? (That's a serious 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 #51
ju**********@yahoo.co.in (junky_fellow) wrote in message news:<8c**************************@posting.google. com>...
Keith Thompson <ks***@mib.org> wrote in message news:<ln************@nuthaus.mib.org>...
ju**********@yahoo.co.in (junky_fellow) writes:
[...]
If on some implementation address 0x12345678 represent a null pointer,
and address 0x0 is a valid address,
then if in my code i deliberately trying to compare some address
with 0x0 ( a valid address ), isn't this wrong on compiler side to
replace this 0x0 with its internal representation on null pointer?


No, it's required.

The confusion is caused by the fact that we're using "0x0" in two
different senses. When you say that 0x0 is a valid address, you mean
(I presume) that an address whose representation is all-bits-zero is
valid -- but if 0x0 appears in a pointer context in C program source,
it refers to a null pointer, however that's represented. (That's why
I've been carefully using the phrase "all-bits-zero" in this thread.)
(although i was trying to compare with some valid location)
Or i should never use hard coded address values except NULL
for pointer comparisons ?


You can use NULL or a literal 0 to refer to a null pointer; they're
equivalent. If you want to use some other numeric value for a
pointer, you're in system-specific territory, and you'd better know
what you're doing.

Read section 5 of the C FAQ if you haven't already.


thanx...


Just one more doubts that i wanted to clarify ....
Consider all-bits-zero a valid address on some machine, and address
0x12345678 represents null pointer.

i have three pointers,
char *ptr1, *ptr2, *ptr3;
ptr1 = NULL; // (null pointer).
ptr2 = (char *)malloc(sizeof(char)); /* and the address returned by OS is 0x0
which is a valid address, i.e ptr2 is
pointing to location 0x0 (all-bits-zero)*/
ptr3 = (char *)0x12345678; /* deliberate assignment to some address */

Now if i compare pointers, (ptr1 == ptr2) what would be the result ?
Theoretically, they shouldn't be equal.

and if i compare (ptr1 == ptr3) what would be the result ?
Nov 14 '05 #52
"Malcolm" <ma*****@55bank.freeserve.co.uk> wrote:
"Mabden" <mabden@sbc_global.net> wrote
NULL is a macro, I agree, for basically (char *)0.
If you look in your standard headers, you could easily find the line
#define NULL ((void *) 0)


You don't know that - it is also reasonably likely to be #defined as a
naked 0, and may, but highly probably isn't, be defined as something as
silly as ('-'-'-').
My point was that null, ie: 0:0, is considered an invalid location for data.
Furthermore, I believe it is "guaranteed" to be invalid for data in C.


It is not guaranteed by the standard.
In practical terms, malloc() will never return a pointer with all bits zero,


You don't know that.
and no item in the stack or in global memory will be all bits zero either.
You don't know that.
This is because the lowest location in memory is always special in some way,
You don't know that.
and even if it wasn't it would be natural to use all bits zero for the null
pointer.


Not if there is another natural invalid pointer on the system, it
wouldn't.

Not all the world is a Wintel box. Not nearly all the world, in fact.

Richard
Nov 14 '05 #53
In article <8c**************************@posting.google.com >,
ju**********@yahoo.co.in (junky_fellow) wrote:
i have three pointers,
char *ptr1, *ptr2, *ptr3;
ptr1 = NULL; // (null pointer).
ptr2 = (char *)malloc(sizeof(char)); /* and the address returned by OS is 0x0
which is a valid address, i.e ptr2 is
pointing to location 0x0
(all-bits-zero)*/
ptr3 = (char *)0x12345678; /* deliberate assignment to some address
*/

Now if i compare pointers, (ptr1 == ptr2) what would be the result ?
Theoretically, they shouldn't be equal.

and if i compare (ptr1 == ptr3) what would be the result ?


Keep in mind that cast from int to char* is "implementation defined" and
doesn't necessarily give a useful result, so if you have a variable "int
x" then "(char *) x == NULL" could be true for many different values of
x.

When you use a cast to convert say from int to float, the bits don't
stay unchanged: int i = 1; float f = (float) i; will produce very
different representations in i and f even though both are equal to one.
Same with a cast to convert from int to char*. Now typically compilers
where a null pointer has an all-bits-zero representation will leave the
representation unchanged, but if a null pointer has the same
representation as 0x12345678 then that would be no good. You would
expect that cast from int to char* will be implemented with machine code
that would map (all bits zero) to the same bit pattern as 0x12345678. It
might add 0x12345678, it might do an xor with 0x12345678. A useful
implementation would try to achieve that (char *) (int) p == p, as long
as sizeof (int) is large enough to hold a pointer. So I would expect
ptr3 and ptr2 to compare not equal.
Nov 14 '05 #54
"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
"Mabden" <mabden@sbc_global.net> writes:
[...]
Of course I get that they don't "need" to point to location zero. Do you
understand that? I gave an example where NULL was pointing to 0x12344321. I get that. NULL or null pointer or whatever does not need to point at
location zero. See, I get it. That's not my point.


Great.
My point is that in addition to the NULL or null of whatever you want to
call the thing, separately, and different from that issue, is that location zero in memory should not be able to store data in a C program.


You're simply wrong about this. Read the reference section (Appendix
A) of K&R2. Read the FAQ, particularly section 5. If you don't have
a copy of the actual C standard, read the relevant portions of the
latest public draft (Google "n869"). Or if you're unwilling to do
that, just listen to the rest of us, who do actually know what we're
talking about.

As you know, the null pointer may or may not be all-bits-zero. As
you've so far refused to acknowledge, the C language says nothing in
particular about an all-bits-zero address; if it's not a null pointer,
it could easily be the address of an object. The only basis for
believing otherwise is a vaguely worded (and arguably incorrect)
sentence on page 102 of K&R2.

BTW, I had forgotten until recently about my previous encounters with
you in this newsgroup. As of just a couple of months ago, you were a
deliberate, self-admitted troll. It's hard to avoid the conclusion
that you haven't changed much. Do you honestly believe that an
all-bits-zero address is somehow special, or are you just trolling
again? (That's a serious question.)


I am not trying to be a troll, altho I do occasionally poke fun at the risk
of being called one.

I'm sorry it may seem that way in this thread, but I have to keep repeating
myself because everyone is running of the mouth about null pointer !=
0x00000000. It is not very pleasant for me to have to keep repeating myself,
and I'm pretty much done now, as I've said my piece and I believe a few
people understand what I'm saying - they don't agree, call me idiot and
prat, etc. but they get my point. I believe you are one of those.

It's actually a silly argument, and I believe it has only gone on this long
because everyone thinks I don't realize that (char *)0 is not at location
zero. I do, and it's not what I'm saying. But you get my point and you say
I'm wrong, which is fine. You haven't been rude (that I recall), which I
also appreciate! So I think we can drop this now. I will just state my
opinion on the issue one last time, but no need to reply, I just want to
wrap up my point one last time.

<opinion>
I am talking about the pg 102 reference, which people are saying is
incorrect or just plain wrong. I don't think it is, or should be.
Apparently, the various Standards (I don't have a copy) is a little vague
about the concept or someone would tell this or that page says location zero
is valid. I, however, take that little snippet in K&R2 as a very easy to
understand concept, and I believe it should be enforced by a compiler.

So regardless what the Standard says, or is, I still believe there should be
(not IS, _should be_) an ultimate place that is NOT implementation defined,
at is always true across all versions of C that can never be used for
storage. A magic location that will fail if you write to it or read from it.
Since we cannot know the largest memory location, why not use the smallest:
0. I also think this concept is hinted at on K&R2 pg 102.
</opinion>

p.s. If, in the future, I say, "Zero is never a valid location..." it is NOT
meant to reopen this argument or troll. It is just an ingrained, knee-jerk
reaction, like saying, "Bless you!" when someone sneezes. Apologies in
advance.

--
Mabden
Nov 14 '05 #55
Keith Thompson wrote:
Having said that, you're assuming that all-bits-zero is the lowest
location in memory. If addresses are treated as signed integers,
all-bits-zero is right in the middle of the address space, and it's
quite likely that something could be allocated there. (I have no idea
whether this applies to any real systems.)


Do transputers count? I believe they had signed addressing.

--
Chris "electric hedgehog" Dollin
C FAQs at: http://www.faqs.org/faqs/by-newsgrou...mp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambl...me_to_clc.html
Nov 14 '05 #56
"Mabden" <mabden@sbc_global.net> writes:
[...]
I am not trying to be a troll, altho I do occasionally poke fun at the risk
of being called one.
Ok, thanks for the clarification (seriously).
I'm sorry it may seem that way in this thread, but I have to keep repeating
myself because everyone is running of the mouth about null pointer !=
0x00000000. It is not very pleasant for me to have to keep repeating myself,
and I'm pretty much done now, as I've said my piece and I believe a few
people understand what I'm saying - they don't agree, call me idiot and
prat, etc. but they get my point. I believe you are one of those.
Yes. (I don't think you're an idiot, just mistaken.)

BTW, in the above paragraph you've just added to the confusion. You
say "null pointr != 0x00000000", but if 0x00000000 is meant to be a C
integer constant, it's a null pointer constant which, when converted
to a pointer type, yields a null pointer. Again, that's why I've been
very careful to use the phrase "all-bits-zero" rather than something
like 0x00000000.

Assuming that all-bits-zero is a null pointer is a common
misconception. Since you clearly misunderstand some aspects of the
relationship between null pointers and various meanings of "zero",
it's easy to assume that you share the more common misconception and
aren't expressing it very well. I think that's why you've needed to
repeat yourself. Apparently you've managed to come up with a brand
new misconception (at least I had never heard of it before) and, after
going back and forth a few times, are expressing it reasonably
clearly.
It's actually a silly argument, and I believe it has only gone on this long
because everyone thinks I don't realize that (char *)0 is not at location
zero.
.... is not *necessarily* at location zero.
I do, and it's not what I'm saying. But you get my point and you say
I'm wrong, which is fine. You haven't been rude (that I recall), which I
also appreciate! So I think we can drop this now. I will just state my
opinion on the issue one last time, but no need to reply, I just want to
wrap up my point one last time.

<opinion>
I am talking about the pg 102 reference, which people are saying is
incorrect or just plain wrong. I don't think it is, or should be.
Apparently, the various Standards (I don't have a copy) is a little vague
about the concept or someone would tell this or that page says location zero
is valid. I, however, take that little snippet in K&R2 as a very easy to
understand concept, and I believe it should be enforced by a compiler.
The standard is not at all vague about this. There is no page in the
standard that says zero is a valid location, because it isn't
necessarily a valid location. Nobody is claiming that all-bits-zero
is *always* a valid address. Nobody other than you is claiming that
all-bits-zero is *never* a valid address. What the standard says
about an all-bits-zero address is the same as what it says about an
all-bits-one address, or an address represented as 0xdeadbeef --
nothing.

Appendix A of K&R2 is a reasonably good reflection of the information
in the standard. Read it.
So regardless what the Standard says, or is, I still believe there
should be (not IS, _should be_) an ultimate place that is NOT
implementation defined, at is always true across all versions of C
that can never be used for storage. A magic location that will fail
if you write to it or read from it. Since we cannot know the
largest memory location, why not use the smallest: 0. I also think
this concept is hinted at on K&R2 pg 102.
</opinion>


If you want to require attempts to write to or read from the
all-bits-zero address to fail, you'll render a number of real-world
systems non-conforming.

<opinion>
Different platforms have different pointer representations. A given
bit pattern representing a valid or invalid address on one system has
no relationship to the same bit pattern representing a valid or
invalid address on another system. It makes no sense to impose any
meaning on one particular bit pattern across all platforms. And since
each platform has a well-defined unique pointer value that denotes no
object (the null pointer), there is simply no need for a second such
value (all-bits-zero).
</opinion>

As for page 102 of K&R2, when I have my copy in front of me I'll send
an e-mail message to Dennis Ritchie and ask for a clarification. I'll
let you know what he says.

--
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 #57
Chris Dollin wrote:
Keith Thompson wrote:
Having said that, you're assuming that all-bits-zero is the lowest
location in memory. If addresses are treated as signed integers,
all-bits-zero is right in the middle of the address space, and
it's quite likely that something could be allocated there. (I
have no idea whether this applies to any real systems.)


Do transputers count? I believe they had signed addressing.


So does (did?) the HP3000.

--
"The most amazing achievement of the computer software industry
is its continuing cancellation of the steady and staggering
gains made by the computer hardware industry..." - Petroski
Nov 14 '05 #58
Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
[...]
Keep in mind that cast from int to char* is "implementation defined" and
doesn't necessarily give a useful result, so if you have a variable "int
x" then "(char *) x == NULL" could be true for many different values of
x.

When you use a cast to convert say from int to float, the bits don't
stay unchanged: int i = 1; float f = (float) i; will produce very
different representations in i and f even though both are equal to one.
Same with a cast to convert from int to char*. Now typically compilers
where a null pointer has an all-bits-zero representation will leave the
representation unchanged, but if a null pointer has the same
representation as 0x12345678 then that would be no good.


I'm going to use the notation $12345678$ to refer to a pointer whose
internal representation is the same as the integer 0x12345678.

Even an implementation with the null pointer represented as
$12345678$, integer to pointer conversions could still leave the bits
unchanged, except in the case of converting a null pointer constant to
a pointer type. Remember that a null pointer constant is a source
construct, and the conversion of a null pointer constant to a pointer
value takes place during compilation. There's no requirement to
duplicate that conversion at run time.

So we could have:

(char*)0 --> $12345678$ (null pointer)
int zero = 0;
(char*)zero --> $00000000$ (non-null pointer)
(char*)0x12345678 --> $12345678$ (happens to be a null pointer)

--
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 #59
I'm trying to let it go, but you just keep baiting me...

"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
"Mabden" <mabden@sbc_global.net> writes:
Assuming that all-bits-zero is a null pointer is a common
misconception. Since you clearly misunderstand some aspects of the
relationship between null pointers and various meanings of "zero",
it's easy to assume that you share the more common misconception and
aren't expressing it very well.
I just haven't stated my point correctly using lawyer-like, perfect
semantics.

Now Keith, I was enjoying the fact that you didn't start assuming ignorance
on my part because you don't agree with my opinion, but you are skating
really close to the line here.

I know all about zero, pointers, etc. My opinion about location zero is not
due to any ignorance in programming C - although I have freely admitted I do
not own a copy of any "Standards" documents other than K&R and K&R2.
I think that's why you've needed to
repeat yourself. Apparently you've managed to come up with a brand
new misconception (at least I had never heard of it before) and, after
going back and forth a few times, are expressing it reasonably
clearly.
Well, then, you admit I am creative, if nothing else. Brand new? You mean
nobody else read the K&R? K&R is known to be subtle and I think this is
merely an overlooked sentence that the "Standard" has ignored for their own
purposes. Can you point me to a web site that discusses whether location
zero should be considered a special case? I think it should. Why do you have
to argue so fiercely against this idea? Are you on the Standards committee?
Am I a C heretic?

Even if I am wrong-headed, isn't it still true that location zero cannot be
written to or read from on YOUR machine. I assume you write C programs, so
just do it and tell me I'm wrong!

All my critics, please just write a simple program to read from location
zero in memory. I you can do it, post what you find there.

That's simple, isn't it?
It's actually a silly argument, and I believe it has only gone on this long because everyone thinks I don't realize that (char *)0 is not at location zero.
... is not *necessarily* at location zero.


Christ, you really are a semantics nitpicker. Yes, not "necessarily" at
zero. Do you want this thread to end or are YOU the troll?
I do, and it's not what I'm saying. But you get my point and you say I'm wrong, which is fine. You haven't been rude (that I recall), which I
also appreciate! So I think we can drop this now. I will just state my
opinion on the issue one last time, but no need to reply, I just want to
wrap up my point one last time.

<opinion>
I am talking about the pg 102 reference, which people are saying is
incorrect or just plain wrong. I don't think it is, or should be.
Apparently, the various Standards (I don't have a copy) is a little vague about the concept or someone would tell this or that page says location zero is valid. I, however, take that little snippet in K&R2 as a very easy to
understand concept, and I believe it should be enforced by a compiler.


The standard is not at all vague about this. There is no page in the
standard that says zero is a valid location, because it isn't
necessarily a valid location. Nobody is claiming that all-bits-zero
is *always* a valid address. Nobody other than you is claiming that
all-bits-zero is *never* a valid address.


I am saying it *should not be* a valid address. IN MY OPINION.
I am not saying that any machine or any compiler or any standard does this.
I am stating that this is how *it should be*.
So regardless what the Standard says, or is, I still believe there
should be (not IS, _should be_) an ultimate place that is NOT
implementation defined, at is always true across all versions of C
that can never be used for storage. A magic location that will fail
if you write to it or read from it. Since we cannot know the
largest memory location, why not use the smallest: 0. I also think
this concept is hinted at on K&R2 pg 102.
</opinion>


If you want to require attempts to write to or read from the
all-bits-zero address to fail, you'll render a number of real-world
systems non-conforming.


Name one.
<opinion>
Different platforms have different pointer representations. A given
bit pattern representing a valid or invalid address on one system has
no relationship to the same bit pattern representing a valid or
invalid address on another system. It makes no sense to impose any
meaning on one particular bit pattern across all platforms. And since
each platform has a well-defined unique pointer value that denotes no
object (the null pointer), there is simply no need for a second such
value (all-bits-zero).
</opinion>
OK, now that's the first response I've had that wasn't insulting or pedantic
or (in my view) wrong. You take my point and respond appropriately. It only
took 50 posts or so to get a legitimate argument. This is the reason I
decided to respond again, after giving up.

I'm not sure how you can know that "each platform has a well-defined unique
pointer value that denotes no object (the null pointer)". What is that value
on the Palm OS? What did NeXT use?
As for page 102 of K&R2, when I have my copy in front of me I'll send
an e-mail message to Dennis Ritchie and ask for a clarification. I'll
let you know what he says.


I assume that is sarcasm? I would LOVE to know what the R thinks, if you can
do that. I suspect it was a joke, and the rest of use emoticons to make that
clear, so a ;-) would have been appropriate.

--
Mabden
Nov 14 '05 #60
Mabden wrote:
I assume that is sarcasm? I would LOVE to know what the R thinks, if you
can do that. I suspect it was a joke, and the rest of use emoticons to
make that clear


[sudden snip]

No, we don't. At least, *this* one doesn't.

[Very, very, rarely, and not in newsgroups.]

--
Chris "electric hedgehog" Dollin
C FAQs at: http://www.faqs.org/faqs/by-newsgrou...mp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambl...me_to_clc.html
Nov 14 '05 #61

In article <bx**************@newssvr21.news.prodigy.com>, "Mabden" <mabden@sbc_global.net> writes:
I'm trying to let it go, but you just keep baiting me...
No one (unless it's someone I've killfiled) in this thread is baiting
you. They're pointing out, in explicit and excruciating detail, how
and why you're wrong - wrong about the facts of the C language, and
wrong to advocate a change to the language.

If you feel you're being baited, that's your problem, not ours.
I know all about zero, pointers, etc. My opinion about location zero is not
due to any ignorance in programming C - although I have freely admitted I do
not own a copy of any "Standards" documents other than K&R and K&R2.
You're certainly ignorant about many C implementations - probably the
majority of implementations, which are freestanding ones for embedded
processors.

If you haven't read the standard, then you're ignorant about how the
C language is actually defined.

And while you claim you've read K&R2, you apparently don't understand
the difference between the tutorial portions and the language specifi-
cation in the appendix, nor do you show an understanding of what's
contained in the latter.
Well, then, you admit I am creative, if nothing else. Brand new? You mean
nobody else read the K&R?
I expect everyone else interpreted the passage in question either in
accordance with the standard (that is, that a zero pointer constant
never refers to a valid object), or misinterpreted it in the common
way (that is, believing that the all-bits-zero address is the same as
a null pointer). Your apparent novelty is in believing that the
authors intended to make the all-bits-zero address forbidden in all C
implementations, and the standard committee somehow neglected to
honor this desire.
K&R is known to be subtle
It's known to be wrong on various points. See Dennis Ritchie's own
list of errata, the link to which has been posted in this very thread.
and I think this is
merely an overlooked sentence that the "Standard" has ignored for their own
purposes.
It's an incorrect, or at least misleading, sentence that the committee
wisely chose to ignore, since that would have broken existing implemen-
tations and made (standard) C unusable on a wide range of platforms.
That seems like an excellent purpose.
Can you point me to a web site that discusses whether location
zero should be considered a special case?
No, because there isn't one, if Keith is correct and this is a novel
misconception on your part.
I think it should. Why do you have
to argue so fiercely against this idea?
I've yet to see anyone in this thread be particularly fierce. Even
the more aggressive c.l.c regulars are being remarkably restrained.
And, of course, they're arguing against your proposal because it's
a terrible idea - it would break existing implementations and make
standard C unusable on a wide range of platforms. (Repeat that to
yourself until you get it.)
Are you on the Standards committee?
How would this be relevant?
Am I a C heretic?
Let's see: you're incorrect about the existing definition and how
it's established; you're advocating a change to the language that
would reduce its utility for no benefit; you're complaining of
persecution... What would you call it?
Even if I am wrong-headed, isn't it still true that location zero cannot be
written to or read from on YOUR machine.
At least one poster (Jack Klein, IIRC) has recently noted that he's
worked on systems where location zero is a valid address. I believe
that was in this thread.
All my critics, please just write a simple program to read from location
zero in memory. I you can do it, post what you find there.
Try it on an older VAX VMS C implementation, and you'll find a zero
there. Because some old C programs relied on this, there are more
recent implementations which support the "zero-address hack" as an
option - an option which does NOT render them non-conforming. IBM's
C for AIX had this option (actually implemented by the linker); I
don't know if it still does, but I have a machine sitting around with
a sufficiently old version of AIX to still provide it.
I am saying it *should not be* a valid address. IN MY OPINION.
I am not saying that any machine or any compiler or any standard does this.
I am stating that this is how *it should be*.
And we're stating that your opinion is wrongheaded, since making
address all-bits-zero invalid on all platforms would be a bad idea.
If you want to require attempts to write to or read from the
all-bits-zero address to fail, you'll render a number of real-world
systems non-conforming.


Name one.


Besides the two hosted implementations I mentioned above, there are
many freestanding implementations - as Jack Klein HAS ALREADY NOTED -
which put something useful at address all-bits-zero.

Embedded processors *greatly* outnumber general-purpose processors.
Many of those embedded processors have freestanding C implementa-
tions, and there are many C programs running on them. I haven't seen
any statistics in this regard, but it's plausible that there are more
C programs running on embedded systems than there are on general-
purpose systems, or more freestanding C implementations than hosted
implementations.

Now, I have no idea how many of those freestanding implementations
make use of address all-bits-zero, or are used on platforms where the
use of address all-bits-zero is determined by the hardware design (so
it might be useful to a C program). However, it is certain that quite
a number of them do.
I'm not sure how you can know that "each platform has a well-defined unique
pointer value that denotes no object (the null pointer)".


Keith knows that's true for all platforms with a conforming C implemen-
tation, because all such implementations must define such a value. In
some cases the platform itself may provide a suitable location; in
others, the implementation may have to pick a location and make sure
that no C object is ever placed there.
As for page 102 of K&R2, when I have my copy in front of me I'll send
an e-mail message to Dennis Ritchie and ask for a clarification. I'll
let you know what he says.


I assume that is sarcasm? I would LOVE to know what the R thinks, if you can
do that.


Dennis Ritchie reads Usenet, including sometimes c.l.c (he's been
active in alt.folklore.computers lately); he reads and responds to
email; and he maintains a list of known errors in K&R2, *as has
already been noted in this thread*. Did you look at the errata
list that someone posted a link to?

--
Michael Wojcik mi************@microfocus.com

Is it any wonder the world's gone insane, with information come to be
the only real medium of exchange? -- Thomas Pynchon
Nov 14 '05 #62
Mabden wrote:
.... snip ...
All my critics, please just write a simple program to read from
location zero in memory. I you can do it, post what you find there.

That's simple, isn't it?


Yup. May not be functional on your system.

c:\c\junk>cat junk.c
#include <stdio.h>

int main(void)
{
long p;

for (p = 0; p < 16; p++) {
printf("{%p) = %x\n", (void*)p, *((char*)p));
}
return 0;
}

c:\c\junk>gcc junk.c

c:\c\junk>.\a
{0) = 50
{1) = ffffff8b
{2) = 45
{3) = 8
{4) = 50
{5) = ffffffe8
{6) = ffffffa6
{7) = fffffff6
{8) = ffffffff
{9) = ffffffff
{a) = ffffff8b
{b) = 45
{c) = ffffffec
{d) = ffffff83
{e) = ffffffc4
{f) = 10

--
"The most amazing achievement of the computer software industry
is its continuing cancellation of the steady and staggering
gains made by the computer hardware industry..." - Petroski
Nov 14 '05 #63
>In article <bx**************@newssvr21.news.prodigy.com>, "Mabden"
<mabden@sbc_global.net> writes:
All my critics, please just write a simple program to read from location
zero in memory. I you can do it, post what you find there.

I have a number of embedded-systems boards accessible to me that have
ordinary RAM at *(char *)0. Put something in there and it is in there;
read from it and you get the same data back:

void showZeros(void) {
char *p = 0;
int i = 0;

*p = 2;
printf("p = %p, *p = %d\n", (void *)p, *p);
p = i;
*p = 3;
printf("p = %p, *p = %d\n", (void *)p, *p);
}

Compiled and run (from the target shell) under vxWorks on various
single-board machines, this produces:

-> showZeros()
p = 0x0, *p = 2
p = 0x0, *p = 3
->

(Both Diab and GNU use all-bits-zero for NULL, even on these
machines that have RAM at location 0.) On other single-board
machines RAM starts "above" 0; where there is ROM at 0 this
produces things like:

p = 0x0, *p = -72
p = 0x0, *p = -72

and where there is nothing at all at zero the task gets a fault
and gets suspended.

In article <news:cf********@news3.newsguy.com>
Michael Wojcik <mw*****@newsguy.com> writes:Try it on an older VAX VMS C implementation, and you'll find a zero
there. Because some old C programs relied on this, there are more
recent implementations which support the "zero-address hack" as an
option - an option which does NOT render them non-conforming. IBM's
C for AIX had this option (actually implemented by the linker); I
don't know if it still does, but I have a machine sitting around with
a sufficiently old version of AIX to still provide it.


4.1BSD on the VAX also had *(char *)0 == 0 (in fact there was a
short-word, 16 bits long, of all-zero-bits at 0). I thought most
VMS systems mapped page zero away, though.

Version 6 Unix on the PDP-11 (other than split I&D) had the magic
number for the a.out format at 0; for OMAGIC binaries (mode 0407)
we had *(char *)0 == 7 (remember that the PDP-11 was "PDP-endian",
little-endian within 16-bit words and big-endian for "long"s stored
as two 16-bit little-endian words). Since C had its main development
on the PDP-11, one might even say that *(char *)0 == 7 was the
*expected* result. :-)

Most peculiar of all, I think, was some code that crept into
System III or System V Unix (not sure which). This is a paraphrase
(I have no recollection of the actual second argument to strcmp()):

if (strcmp(p, "#\307x") == 0)
...

The reason this code got in was that the 3B system on which
the programmer wrote it happened to have an odd sequence of bytes
at *(char *)0, and he wrote that strcmp() call instead of the
correct test:

if (p == NULL)

In other words, whoever wrote this Unix utility, whichever utility
it was (cpio?), thought that *(char *)0 was supposed to contain a
weird string! (I believe I heard this story from Doug Gwyn, who
might remember which utility it was and what the code was. It may
have been Guy Harris. Whoever it was, found the problem by porting
the particular utility and discovering that it did not work on the
new machine.)

The history and "current state of the world" is clear enough, and
mabden@sbc_global.net is simply wrong. The C Standards are a
little tougher to read and interpret, but overall, the facts are:

- The NULL macro, and the null pointer constants, are source
code constructs.

- A compiler's job is to convert source code constructs to
suitable machine code. This allows the compiler to change
"what you see in the source" to "what you will see if you
disassemble the machine code". That is, there is some
mapping between "external" representation -- what you type
into a C program, or see when you printf() -- and "internal"
representation, as used by machine-level code.

- The Standards allow the machine code to use any particular bit
pattern(s) the implementor chooses to represent various null
pointers internally, *provided* that no valid C object's address
(nor function pointer) compares equal to any such null pointer.

- Most implementors use all-bits-zero for internal null pointers.
It is usually the easiest thing to do, and most people usually
do the easiest thing. But other bit patterns are allowed, and
some machines have particularly complicated pointers (e.g.,
IBM AS/400) so that all-bits-zero is not easiest after all.

- Many machines without virtual memory, and even some with, have
ROM or RAM at physical address 0.

- C implementations that use all-bits-zero for all their internal
null pointers *and* that have useable RAM at address 0 must
make sure not to put any C object or function at address zero,
which is typically easily achieved by putting some "non-C"
thing there, such as startup code or a "shim".

- Many implementations with virtual memory simply map out address
0 so that improper attempts to access it are caught right away.
This is a good thing, but is not required by the C Standards.

- C implementations that use something other than "hardware
address 0" for their internal null pointers *and* that have
useful stuff at "hardware address zero" are not actually
obligated to let you get at the useful stuff -- nobody ever
said C *has* to be useful for systems programmers -- but will
likely have some trick(s) you can use to do that, because
most systems programmers *like* their C systems to be useful
to them. (After all, why buy a C compiler if you cannot *use*
it?)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #64
"Mabden" <mabden@sbc_global.net> writes:
I'm trying to let it go, but you just keep baiting me...
You persist in making inaccurate statements. Nobody is baiting you;
we're only interested in accuracy.

BTW, Michael Wojcik and Chris Torek have answered several of your
questions; I've read their responses and I believe they're entirely
accurate.
"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
"Mabden" <mabden@sbc_global.net> writes:
Assuming that all-bits-zero is a null pointer is a common
misconception. Since you clearly misunderstand some aspects of the
relationship between null pointers and various meanings of "zero",
it's easy to assume that you share the more common misconception and
aren't expressing it very well.
I just haven't stated my point correctly using lawyer-like, perfect
semantics.

Now Keith, I was enjoying the fact that you didn't start assuming
ignorance on my part because you don't agree with my opinion, but
you are skating really close to the line here.

I know all about zero, pointers, etc. My opinion about location zero
is not due to any ignorance in programming C - although I have
freely admitted I do not own a copy of any "Standards" documents
other than K&R and K&R2.


You could if you wanted to. Visit
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n869/>
and you can get a copy of the latest public draft of the C99 standard
in PDF, Postscript, or plain text. The actual standard differs in
some areas, but I don't believe there are any differences relevant to
the current discussion.

Or you could pay $18 or so for a copy of the actual standard, but
that's not necessary for the current discussion.

In the above quoted paragraph where I wrote that "it's easy to assume
that you share the more common misconception and aren't expressing it
very well", I was not accusing you of expressing yourself unclearly.
I was trying to explain why, due to (what I see as) the unusual nature
of your misconception, a lot of us might have assumed that you're
expressing yourself unclearly.

My strong opinion is that, on this particular point, I'm right and
you're wrong, and that my opinion is based on better sources of
information than yours. I'm not implying that you're a generally
ignorant person, only that you happen to be ignorant on this
particular point. It's nothing personal. Let's both continue working
to keep it that way.

[...] Even if I am wrong-headed, isn't it still true that location zero cannot be
written to or read from on YOUR machine. I assume you write C programs, so
just do it and tell me I'm wrong!

All my critics, please just write a simple program to read from location
zero in memory. I you can do it, post what you find there.

That's simple, isn't it?
Others have done so in this thread. I'm unable to do so myself,
because all the C implementations to which I currently have access
happen to use all-bits-zero to represent null pointers, and happen to
trap on attempts to dereference a null pointer. (I don't work with
embedded systems other than as an end user.)

Note that C doesn't require a trap for *any* pointer deference,
whether it's null, all-bits-zero, deallocated, uninitialized, or
random. Most such dereferences invoke undefined behavior. One of the
infinitely many possible results of undefined behavior is to quietly
fetch a valid value from the specified location.

(BTW, there's a point that I've ignored so far. A null pointer
doesn't necessarily have the same representation for all pointer
types. Not all pointer types even have to have the same
representation; for example, function pointers might be bigger than
data pointers. This isn't critical to the current discussion, and we
can safely restrict the discussion to systems where all data pointers
look alike and have a unique representation for the null pointer.
This restriction still lets us talk about systems where the
representation of a null pointer is not all-bits-zero.)
It's actually a silly argument, and I believe it has only gone
on this long because everyone thinks I don't realize that (char
*)0 is not at location zero.


... is not *necessarily* at location zero.


Christ, you really are a semantics nitpicker. Yes, not "necessarily" at
zero. Do you want this thread to end or are YOU the troll?


We're talking about a fairly subtle point, so precision is
extraordinarily important. We all make mistakes; whining when someone
corrects them is not constructive.

[...] I am saying it *should not be* a valid address. IN MY OPINION. I am
not saying that any machine or any compiler or any standard does
this. I am stating that this is how *it should be*.
A serious question: if that sentence on page 102 of K&R2 weren't
there, would you still hold this opinion? What if the errata page
were updated to clarify that there's nothing special about an
all-bits-zero address (unless that happens to be the representation of
a null pointer)?

I have a lot of opinions about the way C *should be* (or, more
accurately, about the way it should have been). Many of them directly
contradict the actual language as defined by the standard and
described by various books including K&R2. I try to make it very
clear that these are just my opinions, and they're not about what the
language *is*, merely about what I might like it to be in an ideal
world.

I think you've been saying one (or both) of two things:

(1) The C language actually requires an attempt to read or write to the
all-bits-zero address to fail; or

(2) In your opinion, the C language *should* require an attempt to read
or write to the all-bits-zero address to fail.

I've been unsure about which of these things you're actually saying.
(That may very well be my fault.) Can you clarify, even if you think
you already have?

If your point is (1), my response is that you are mistaken, and that
this is easily documented. If your point is (2), I suppose I can't
say that you're mistaken, but I strongly believe that such a
requirement would be a bad idea; it would add confusion to an already
confusing area of the language with no real benefit that I can think
of. Systems that should trap on references to the all-bits-zero
address already do; systems that don't, probably shouldn't.
If you want to require attempts to write to or read from the
all-bits-zero address to fail, you'll render a number of real-world
systems non-conforming.


Name one.


I can't, but others have provided concrete examples.

[...]
I'm not sure how you can know that "each platform has a well-defined
unique pointer value that denotes no object (the null
pointer)". What is that value on the Palm OS? What did NeXT use?


On Palm OS, that value is the null pointer. On NeXT, that value is
the null pointer. I don't know how that value is represented, but
it's likely that it's all-bits-zero in both cases.

I should have said "each C implementation" rather than "each
platform". I know that each C implementation has a null pointer value
because the standard requires it.

(Again, I'm glossing over the possibility of different null pointer
values for different pointer types. Strictly speaking, there's a
distinct null pointer value for each pointer type in each C
implementation. Realistically, it's likely to have the same
representation for void* and all object pointer types for almost all
implementations, even those where a null pointer is something other
than all-bits-zero, but I wouldn't be astonished if there were
counterexamples.)
As for page 102 of K&R2, when I have my copy in front of me I'll send
an e-mail message to Dennis Ritchie and ask for a clarification. I'll
let you know what he says.


I assume that is sarcasm? I would LOVE to know what the R thinks, if
you can do that. I suspect it was a joke, and the rest of use
emoticons to make that clear, so a ;-) would have been appropriate.


No, I'm completely serious. Why do you assume that I'm being
sarcastic?

--
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 #65

"Old Wolf" <ol*****@inspire.net.nz> wrote in message
This code is undefined

char *ptr = 0;

*ptr = 1;


What has that got to do with the location zero?

Read all of a post before hitting the reply button. The answer is of course
nothing, according to a literal interpretation of the modern standard,
though historically 0 represents the null pointer because it was always
absolute location zero.
Nov 14 '05 #66
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
[...]
Keep in mind that cast from int to char* is "implementation defined" and
doesn't necessarily give a useful result, so if you have a variable "int
x" then "(char *) x == NULL" could be true for many different values of
x.

When you use a cast to convert say from int to float, the bits don't
stay unchanged: int i = 1; float f = (float) i; will produce very
different representations in i and f even though both are equal to one.
Same with a cast to convert from int to char*. Now typically compilers
where a null pointer has an all-bits-zero representation will leave the
representation unchanged, but if a null pointer has the same
representation as 0x12345678 then that would be no good.
I'm going to use the notation $12345678$ to refer to a pointer whose
internal representation is the same as the integer 0x12345678.

Even an implementation with the null pointer represented as
$12345678$, integer to pointer conversions could still leave the bits
unchanged, except in the case of converting a null pointer constant to
a pointer type. Remember that a null pointer constant is a source
construct, and the conversion of a null pointer constant to a pointer
value takes place during compilation.


No, it does not, at least not in C99.

For example, in the definition of "equality operator" it says

Constraints: (three other possibilities and)
One operand is a pointer and the other is a null pointer constant.

Semantics: (two other possibilities and)
Otherwise, at least one operand is a pointer. If one operand is a
null pointer constant, it is converted to the type of the other operand.

Conversion is done according to exactly the same rules as all other
conversions; since a null pointer constant is either of an integral type
or of type void*, that conversion is either a conversion from an
integral type to a pointer type or from void* to another pointer type.
But there is no difference between this conversion and any other
conversion. It is conceptually not a compile time construct. (Of course
an optimiser will determine the result of the conversion at compile
time, just as 2+3 will be determined at compile time by practically
every compiler).
There's no requirement to
duplicate that conversion at run time.

So we could have:

(char*)0 --> $12345678$ (null pointer)
int zero = 0;
(char*)zero --> $00000000$ (non-null pointer)
(char*)0x12345678 --> $12345678$ (happens to be a null pointer)


Quite possible in C90, but most definitely not in C99. In C90, the
wording was such that in an assignment, or within an equality operator,
and probably some cases that I forgot, a null pointer constant was
replaced with a null pointer. (char*)0 was _not_ one if these cases and
in C90 not guaranteed to be a null pointer; in C99 they added that
_every_ conversion of a null pointer constant to a pointer produces a
null pointer.
Nov 14 '05 #67
"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
"Mabden" <mabden@sbc_global.net> writes:
My strong opinion is that, on this particular point, I'm right and
you're wrong, and that my opinion is based on better sources of
information than yours.
Well then I guess I had better change my opinion on this matter then. Thank
you for the enlightenment. I will leave this thread a wiser mabden.
All my critics, please just write a simple program to read from location
zero in memory. I you can do it, post what you find there.

That's simple, isn't it?


Others have done so in this thread. I'm unable to do so myself,
because all the C implementations to which I currently have access
happen to use all-bits-zero to represent null pointers, and happen to
trap on attempts to dereference a null pointer.


Aha, gotcha! Just kidding.

(BTW, there's a point that I've ignored so far. A null pointer
doesn't necessarily have the same representation for all pointer
types. Not all pointer types even have to have the same
representation; for example, function pointers might be bigger than
data pointers. This isn't critical to the current discussion, and we
can safely restrict the discussion to systems where all data pointers
look alike and have a unique representation for the null pointer.
This restriction still lets us talk about systems where the
representation of a null pointer is not all-bits-zero.)
This is a good point, tho, and really caused me to change my mind about the
zero location issue. I realized I had no answer for the question, "How BIG
should a zero location null pointer be, exactly?" Especially considering
moving into C++ objects; how would that be backwards-compatible? I actually
wish you HAD brought this up earlier.
[...]
I am saying it *should not be* a valid address. IN MY OPINION. I am
not saying that any machine or any compiler or any standard does
this. I am stating that this is how *it should be*.
A serious question: if that sentence on page 102 of K&R2 weren't
there, would you still hold this opinion? What if the errata page
were updated to clarify that there's nothing special about an
all-bits-zero address (unless that happens to be the representation of
a null pointer)?


No. My opinion is from that statement alone. I see^h^haw it as a Good Thing,
and believed it to be true. In fact, in my experience it HAS been true. I
don't work on embedded devices (other than Palms, if they are considered
such) or VAXen so my world view encompassed this notion fully.

I have a lot of opinions about the way C *should be* (or, more
accurately, about the way it should have been). Many of them directly
contradict the actual language as defined by the standard and
described by various books including K&R2. I try to make it very
clear that these are just my opinions, and they're not about what the
language *is*, merely about what I might like it to be in an ideal
world.

I think you've been saying one (or both) of two things:

(1) The C language actually requires an attempt to read or write to the
all-bits-zero address to fail; or
Yes, I believed this, but modified by belief to the next one when I was told
I was mistaken and it does not. I thought it was a Rule.
(2) In your opinion, the C language *should* require an attempt to read
or write to the all-bits-zero address to fail.
As a general "fail-safe", no matter what platform, no matter what compiler,
lifeline. An assurance that I could KNOW where a null pointer is, since as
we've discussed (void *)0 can be anywhere the compiler decides. I see the
light now, and repent my ways. No Real Programmer needs such a construct.
If your point is (1), my response is that you are mistaken, and that
this is easily documented. If your point is (2), I suppose I can't
say that you're mistaken, but I strongly believe that such a
requirement would be a bad idea; it would add confusion to an already
confusing area of the language with no real benefit that I can think
of. Systems that should trap on references to the all-bits-zero
address already do; systems that don't, probably shouldn't.


Gotcha.
If you want to require attempts to write to or read from the
all-bits-zero address to fail, you'll render a number of real-world
systems non-conforming.


Name one.


I can't, but others have provided concrete examples.


More like sandstone.
Some have read from the location, which may be system code. I didn't see
anyone write a value and read it back out, but I may have missed something.
Chris did this:
void showZeros(void) {
char *p = 0;
int i = 0;

*p = 2;
printf("p = %p, *p = %d\n", (void *)p, *p);
p = i;
*p = 3;
printf("p = %p, *p = %d\n", (void *)p, *p);
}
But that's just a 0 in memory, isn't it? Especially p=i; Anyway it's run on
an emulator, so how valid is that?

CBFalconer just reads. I've never said that zero location can't be system
code, altho I desired it to be unreadable in C (before my conversion). But
my main point was for zero to be unwritable (which is wrong, which is wrong,
which is wrong!).
As for page 102 of K&R2, when I have my copy in front of me I'll send
an e-mail message to Dennis Ritchie and ask for a clarification. I'll
let you know what he says.


I assume that is sarcasm? I would LOVE to know what the R thinks, if
you can do that. I suspect it was a joke, and the rest of use
emoticons to make that clear, so a ;-) would have been appropriate.


No, I'm completely serious. Why do you assume that I'm being
sarcastic?


I guess it's like talking to God or something. Unbelievable, that mere
mortals could engage The Writer of the Holy K&R.

Well, thanks again for your patient explanations. I have been converted and
I will try not to spout nonsense about Location Zero again.

Of course, other nonsense may slip through my fingers from time to time...
;)

--
Mabden

Nov 14 '05 #68
"Mabden" <mabden@sbc_global.net> writes:
[...]
Well, thanks again for your patient explanations. I have been converted and
I will try not to spout nonsense about Location Zero again.
But, but ... you mean you've changed your mind, and admitted you were
wrong? This is Usenet; we don't do that here! Arguments are supposed
to continue without resolution until everybody has killfiled everybody
else and we're all left with nothing but simmering contempt.

Seriously, I'm glad to hear it. It's nice to see that sticky
questions can actually be resolved sometimes.
Of course, other nonsense may slip through my fingers from time to time...
;)


And mine.

--
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 #69
In article <84***************@newssvr21.news.prodigy.com>
Mabden <mabden@sbc_global.net> writes:
Chris did this:
void showZeros(void) {
char *p = 0;
int i = 0;

*p = 2;
printf("p = %p, *p = %d\n", (void *)p, *p);
p = i;
*p = 3;
printf("p = %p, *p = %d\n", (void *)p, *p);
}
But that's just a 0 in memory, isn't it?
What do you mean by "a 0 in memory"? These machines (PowerPC, MIPS32,
ARM32, Pentium, SPARC32) all have 32-bit-integer 32-bit-pointer flat
address space architectures (as configured anyway; some are capable of
other arrangements). Some of them have RAM at hardware address zero,
some have ROM, some have nothing at all.
Especially p=i; Anyway it's run on an emulator,


What makes you think it is "run on an emulator"? While we (Wind
River) do have two "vxsim" systems, one for Linux and one for SPARC,
we also supply code for MIPS, PowerPC, ARM, and other machines.
I have a PowerPC-based single-board computer here (the "wrsbc8260"),
and, via the "virtual lab manager", access to various other machines.
(I happen to *prefer* using vxsim on the Linux box, as it is fast
and convenient. But we have to test everything on everything, as
it were -- Diab and gcc, on simulators and real hardware, compiled
with each of the various supported "bsp"s as they are called.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #70


Christian Bau wrote:
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:

Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
[...]
Keep in mind that cast from int to char* is "implementation defined" and
doesn't necessarily give a useful result, so if you have a variable "int
x" then "(char *) x == NULL" could be true for many different values of
x.

When you use a cast to convert say from int to float, the bits don't
stay unchanged: int i = 1; float f = (float) i; will produce very
different representations in i and f even though both are equal to one.
Same with a cast to convert from int to char*. Now typically compilers
where a null pointer has an all-bits-zero representation will leave the
representation unchanged, but if a null pointer has the same
representation as 0x12345678 then that would be no good.
I'm going to use the notation $12345678$ to refer to a pointer whose
internal representation is the same as the integer 0x12345678.

Even an implementation with the null pointer represented as
$12345678$, integer to pointer conversions could still leave the bits
unchanged, except in the case of converting a null pointer constant to
a pointer type. Remember that a null pointer constant is a source
construct, and the conversion of a null pointer constant to a pointer
value takes place during compilation.

No, it does not, at least not in C99.

For example, in the definition of "equality operator" it says

Constraints: (three other possibilities and)
One operand is a pointer and the other is a null pointer constant.

Semantics: (two other possibilities and)
Otherwise, at least one operand is a pointer. If one operand is a
null pointer constant, it is converted to the type of the other operand.

Conversion is done according to exactly the same rules as all other
conversions; since a null pointer constant is either of an integral type
or of type void*, that conversion is either a conversion from an
integral type to a pointer type or from void* to another pointer type.
But there is no difference between this conversion and any other
conversion. It is conceptually not a compile time construct. (Of course


OK, you lost me here. When talking about the null pointer constant (or
any constant for that matter), doesn't that mean that they are available
(as constants) at compile time? Does it make sense to talk about a
non-compile-time constant?
an optimiser will determine the result of the conversion at compile
time, just as 2+3 will be determined at compile time by practically
every compiler).

There's no requirement to
duplicate that conversion at run time.

So we could have:

(char*)0 --> $12345678$ (null pointer)
int zero = 0;
(char*)zero --> $00000000$ (non-null pointer)
(char*)0x12345678 --> $12345678$ (happens to be a null pointer)

Quite possible in C90, but most definitely not in C99. In C90, the
wording was such that in an assignment, or within an equality operator,
and probably some cases that I forgot, a null pointer constant was
replaced with a null pointer. (char*)0 was _not_ one if these cases and


I thought that casting constant 0 to any pointer type produced the
null pointer; is this not the case?
in C90 not guaranteed to be a null pointer; in C99 they added that
_every_ conversion of a null pointer constant to a pointer produces a
null pointer.


--
Ron Collins
Air Defense/RTSC/BCS
"I have a plan so cunning, you could put a tail on it and call it a weasel"

Nov 14 '05 #71
Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
[...]
Keep in mind that cast from int to char* is "implementation defined" and
doesn't necessarily give a useful result, so if you have a variable "int
x" then "(char *) x == NULL" could be true for many different values of
x.

When you use a cast to convert say from int to float, the bits don't
stay unchanged: int i = 1; float f = (float) i; will produce very
different representations in i and f even though both are equal to one.
Same with a cast to convert from int to char*. Now typically compilers
where a null pointer has an all-bits-zero representation will leave the
representation unchanged, but if a null pointer has the same
representation as 0x12345678 then that would be no good.
I'm going to use the notation $12345678$ to refer to a pointer whose
internal representation is the same as the integer 0x12345678.

Even an implementation with the null pointer represented as
$12345678$, integer to pointer conversions could still leave the bits
unchanged, except in the case of converting a null pointer constant to
a pointer type. Remember that a null pointer constant is a source
construct, and the conversion of a null pointer constant to a pointer
value takes place during compilation.


No, it does not, at least not in C99.


You're right that the language doesn't require the conversion to be
done during compilation; I was sloppy there. (But of course it can
be, and it typically is.)
For example, in the definition of "equality operator" it says

Constraints: (three other possibilities and)
One operand is a pointer and the other is a null pointer constant.

Semantics: (two other possibilities and)
Otherwise, at least one operand is a pointer. If one operand is a
null pointer constant, it is converted to the type of the other operand.

Conversion is done according to exactly the same rules as all other
conversions; since a null pointer constant is either of an integral type
or of type void*, that conversion is either a conversion from an
integral type to a pointer type or from void* to another pointer type.
But there is no difference between this conversion and any other
conversion. It is conceptually not a compile time construct. (Of course
an optimiser will determine the result of the conversion at compile
time, just as 2+3 will be determined at compile time by practically
every compiler).


Conversion of a null pointer constant to a pointer type is explicitly
a special case, at least in C99. (I think that was the intent in C90
as well, but C99 expresses it better; this is speculation on my part.)
There's no requirement to
duplicate that conversion at run time.

So we could have:

(char*)0 --> $12345678$ (null pointer)
int zero = 0;
(char*)zero --> $00000000$ (non-null pointer)
(char*)0x12345678 --> $12345678$ (happens to be a null pointer)


Quite possible in C90, but most definitely not in C99. In C90, the
wording was such that in an assignment, or within an equality operator,
and probably some cases that I forgot, a null pointer constant was
replaced with a null pointer. (char*)0 was _not_ one if these cases and
in C90 not guaranteed to be a null pointer; in C99 they added that
_every_ conversion of a null pointer constant to a pointer produces a
null pointer.


Here's the C90 wording, with underscores denoting italics:

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.

Two null pointers. converted through possibly different sequences
of casts to pointer types, shall compare equal.

C99 says:

An integer 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 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.

Conversion of a null pointer to another pointer type yields a null
pointer of that type. Any two null pointers shall compare equal.

In my opinion, C99's statement that a null pointer constant yields a
null pointer when converted to a pointer type does not imply that all
expressions of type int with value 0 yield a null pointer when
converted to a pointer type.

In my example above, I presume the part you disagree with is my
assertion that, given "int zero = 0;", the expression "(char*)zero"
needn't yield a null pointer. Since "zero" is not a null pointer
constant

Your assumption, I think, is that conversion of a given value from a
given type to another given type (in this case, respectively, the
value 0, the type int, and the type char*) must always yield the same
result. That's not a reasonable expectation, but I think it's
overridden by the fact that conversion of a "null pointer constant" is
explicitly a special case.

More concretely:

#include <stdio.h>
#include <string.h>

static int equal(char *x, char *y)
{
return memcmp(&x, &y, sizeof(char*)) == 0;
}

int main(void)
{
char *null_pointer = 0;
char *all_bits_zero_pointer;
int zero = 0;
char *maybe_null_pointer = (char*)zero;

memset(&all_bits_zero_pointer, 0, sizeof all_bits_zero_pointer);

if (equal(null_pointer, all_bits_zero_pointer)) {
printf("A null pointer is all-bits-zero\n");
}
else {
printf("A null pointer is not all-bits-zero\n");
}

if (equal(null_pointer, maybe_null_pointer)) {
printf("Conversion of int zero yields a null pointer\n");
}
else {
printf("Conversion of int zero does not yield a null pointer\n");
}

return 0;
}

I'm using memcmp rather than direct pointer comparison to avoid any
possibility of undefined behavior on attempts to access the value of
an invalid pointer.

I think we all agree that the first line of output from this program
may be either
A null pointer is all-bits-zero
or
A null pointer is not all-bits-zero

I assert that, regardless of the first line of output, the second line
can be either
Conversion of int zero yields a null pointer
or
Conversion of int zero does not yield a null pointer
under a conforming implementation -- though an implementation would
have to be particularly perverse to produce
A null pointer is not all-bits-zero
Conversion of int zero does not yield a null pointer

(The output happens to be
A null pointer is all-bits-zero
Conversion of int zero yields a null pointer
on all systems I'm familiar with; that's not very illuminating.)

To put it another way, I believe that choosing a value other than
all-bits-zero for the null pointer does not imply that
integer-to-pointer conversion has to do anything other than a bitwise
copy *except* in the case of a null pointer constant.

--
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 #72
RCollins <rc***@nospam.theriver.com> writes:
[...]
OK, you lost me here. When talking about the null pointer constant (or
any constant for that matter), doesn't that mean that they are available
(as constants) at compile time? Does it make sense to talk about a
non-compile-time constant?
The null pointer constant itself exists only in the C program source.
Christian's point, I think, is that the *conversion* doesn't
necessarily take place at compile time (and he's correct).

For example, given:

char *ptr = 0;

the expression 0 is implicitly converted to char*. If this conversion
is non-trivial (something other than just copying the bits), it could
easily take place at run time, as long as it yields a null pointer
value.
I thought that casting constant 0 to any pointer type produced the
null pointer; is this not the case?


Yes, that is the case. The question is whether casting a non-constant
value 0 to a pointer type necessarily yields a null pointer.

Given "int zero = 0;", if you assume that all conversions are
performed at run time, it's difficult to imagine that (char*)0 and
(char*)zero could yield different results; it seems obvious that they
should be equivalent. Likewise, if you assume that all conversions
are done *as if* they were performed at run time, the situation is the
same. The question is whether the standard's treatment of conversion
of a null pointer constant as a special case is enough to allow this
equivalence to be broken. I think it is; Christian thinks it isn't.

I'm beginning to think this may call 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 #73
"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
"Mabden" <mabden@sbc_global.net> writes:
[...]
Well, thanks again for your patient explanations. I have been converted and I will try not to spout nonsense about Location Zero again.


But, but ... you mean you've changed your mind, and admitted you were
wrong? This is Usenet; we don't do that here! Arguments are supposed
to continue without resolution until everybody has killfiled everybody
else and we're all left with nothing but simmering contempt.


<best Homer Simpson voice> Doh!

But, not to worry, I think I saw someone else pick up the "(void *)0 isn't
location zero" argument again, so we can sit back and watch the
merry-go-round again, and again, and again, and again, and again, and again,
and again. <falls over dizzy>

Is there any magic way to say, "Hey! I started this thread, and I'm done, so
ya'll stop now, y'hear."?

Wait! I know how!!!!

You're all a bunch of Language Nazis!!!

That should to do it!
--
Mabden
Nov 14 '05 #74


Keith Thompson wrote:
RCollins <rc***@nospam.theriver.com> writes:
[...]
OK, you lost me here. When talking about the null pointer constant (or
any constant for that matter), doesn't that mean that they are available
(as constants) at compile time? Does it make sense to talk about a
non-compile-time constant?

The null pointer constant itself exists only in the C program source.
Christian's point, I think, is that the *conversion* doesn't
necessarily take place at compile time (and he's correct).


Ah ... gotcha. I was mis-reading the earlier posts about where the
conversion takes place.

For example, given:

char *ptr = 0;

the expression 0 is implicitly converted to char*. If this conversion
is non-trivial (something other than just copying the bits), it could
easily take place at run time, as long as it yields a null pointer
value.

I thought that casting constant 0 to any pointer type produced the
null pointer; is this not the case?

Yes, that is the case. The question is whether casting a non-constant
value 0 to a pointer type necessarily yields a null pointer.

Given "int zero = 0;", if you assume that all conversions are
performed at run time, it's difficult to imagine that (char*)0 and
(char*)zero could yield different results; it seems obvious that they
should be equivalent. Likewise, if you assume that all conversions
are done *as if* they were performed at run time, the situation is the
same. The question is whether the standard's treatment of conversion
of a null pointer constant as a special case is enough to allow this
equivalence to be broken. I think it is; Christian thinks it isn't.

I'm beginning to think this may call for a DR.


--
Ron Collins
Air Defense/RTSC/BCS
"I have a plan so cunning, you could put a tail on it and call it a weasel"

Nov 14 '05 #75
Mabden wrote:
.... snip ...
CBFalconer just reads. I've never said that zero location can't
be system code, altho I desired it to be unreadable in C (before
my conversion). But my main point was for zero to be unwritable
(which is wrong, which is wrong, which is wrong!).


Because I have no idea what is actually at location 0 and what it
does, and no interest in finding out. I expect reading to be
non-harmful to my system. I have great qualms about writing
thereto.

--
"The most amazing achievement of the computer software industry
is its continuing cancellation of the steady and staggering
gains made by the computer hardware industry..." - Petroski
Nov 14 '05 #76
"CBFalconer" <cb********@yahoo.com> wrote in message
news:41***************@yahoo.com...
Mabden wrote:

... snip ...

CBFalconer just reads. I've never said that zero location can't
be system code, altho I desired it to be unreadable in C (before
my conversion). But my main point was for zero to be unwritable
(which is wrong, which is wrong, which is wrong!).


Because I have no idea what is actually at location 0 and what it
does, and no interest in finding out. I expect reading to be
non-harmful to my system. I have great qualms about writing
thereto.


Not to worry, it's guaranteed not to work!
Doh! Backsliding...!
Sorry, I had to do that... :)

It'd probably just overwrite some lowlevel boot loader or something. Here's
an idea, tho, read from Location Zero and write back the same value. Or
better yet write back something else, to show it can change, then put back
the original value. Then reboot.

--
Mabden
Nov 14 '05 #77
In article <cf**********@pita.alt.net>,
RCollins <rc***@nospam.theriver.com> wrote:
Christian Bau wrote:
Quite possible in C90, but most definitely not in C99. In C90, the
wording was such that in an assignment, or within an equality operator,
and probably some cases that I forgot, a null pointer constant was
replaced with a null pointer. (char*)0 was _not_ one if these cases and


I thought that casting constant 0 to any pointer type produced the
null pointer; is this not the case?


In C90 it was _not_ the case. There was _no_ rule in C90 that said that
casting constant 0 to any pointer type produced a null pointer. There
were rules saying that in certain situations a null pointer constant is
replaced by a null pointer, casting 0 to char* was not one of these
situations. In C99, this has been changed. A null pointer constant is
not replaced by a null pointer anymore, a conversion takes place
instead. Some other rule then guarantees that _all_ conversions from
null pointer constants to pointer types yield null pointers.
Nov 14 '05 #78

In article <ln************@nuthaus.mib.org>, Keith Thompson <ks***@mib.org> writes:

Given "int zero = 0;", if you assume that all conversions are
performed at run time, it's difficult to imagine that (char*)0 and
(char*)zero could yield different results; it seems obvious that they
should be equivalent.


It's not obvious to me. (char*)0 is a null pointer constant, cast to
a char*. (char*)zero is an int variable value cast to char*. zero
is not a constant here, it does not meet the C99 definition of a null
pointer constant (as it is not an integer constant expression, nor
such an expression cast to void*), and operations on it need not obey
the null pointer constant rules in any fashion.

Consider in particular:

{
extern int zero;
char *p;

p = (char*)zero;
}

The value of zero when this block is executed may be 0, but that
can't be known at compile time, which would mean that if Christian
is correct the implementation would *have* to generate code to
check if the current value of zero is 0 before performing the
conversion. It's obvious *to me* that such a requirement is
unnecessarily burdensome, and I don't see it anywhere in the n869.
Perhaps it's in the final standard, but I haven't seen any quoted
text from that in this thread that would lead me to believe that,
either.

What it comes down to is simply that no expression involving a
variable is a null pointer constant, because null pointer constants
are always integer constant expressions. More specifically:

[#6] An integer constant expression87) shall have integer
type and shall only have operands that are integer
constants, enumeration constants, character constants,
sizeof expressions whose results are integer constants, and
floating constants that are the immediate operands of casts.
(n869 6.5.17)

So no expression containing a variable can be a null pointer
constant. Further, my interpretation of n869 6.5.4 #4 is that
an implementation would be non-conforming if it treated a non-
constant integer expression with value 0 as a null pointer
constant, if that implementation did not use all-bits-zero as
the null pointer value, because a cast "converts the value of
the expression to the named type". If the value of the integer
variable zero is 0, then casting it to char* should produce a
char* type object with value all-bits-zero.

--
Michael Wojcik mi************@microfocus.com

There are many definitions of what art is, but what I am convinced art is not
is self-expression. If I have an experience, it is not important because it
is mine. It is important because it's worth writing about for other people,
worth sharing with other people. That is what gives it validity. (Auden)
Nov 14 '05 #79
mw*****@newsguy.com (Michael Wojcik) writes:
In article <ln************@nuthaus.mib.org>, Keith Thompson
<ks***@mib.org> writes:
Given "int zero = 0;", if you assume that all conversions are
performed at run time, it's difficult to imagine that (char*)0 and
(char*)zero could yield different results; it seems obvious that they
should be equivalent.


It's not obvious to me. (char*)0 is a null pointer constant, cast to
a char*. (char*)zero is an int variable value cast to char*. zero
is not a constant here, it does not meet the C99 definition of a null
pointer constant (as it is not an integer constant expression, nor
such an expression cast to void*), and operations on it need not obey
the null pointer constant rules in any fashion.


Note the qualification: "if you assume that all conversions are
performed at run time ...". With that assumption, it follows, I
think, that (char*)0 and (char*)zero would yield the same value (which
must be a null pointer).

In fact, I don't make that assumption. In my opinion, an
implementation could legitimately perform the conversion in (char*)0
at compilation time (yielding a null pointer), and perform the
conversion in (char*)zero at run time (yielding, most likely, and
all-bits-zero pointer).

I was trying to present the other side of the argument. It looks like
I inadvertently convinced you that I believe it. At least I didn't
convince you that it's correct. 8-)}

--
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 #80
CBFalconer wrote:
Mabden wrote:

... snip ...
CBFalconer just reads. I've never said that zero location can't
be system code, altho I desired it to be unreadable in C (before
my conversion). But my main point was for zero to be unwritable
(which is wrong, which is wrong, which is wrong!).

Because I have no idea what is actually at location 0 and what it
does, and no interest in finding out. I expect reading to be
non-harmful to my system. I have great qualms about writing
thereto.


Indeed. There is no correlation (that we can know) between a C
pointer value and a physical memory address. The C program is too
far from the metal.

The likelihood that NULL will actually point to physical address 0
in memory is remote if not impossible.

We are all talking about 'hosted' environments, right?
--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #81
In article <cf*********@news3.newsguy.com>,
mw*****@newsguy.com (Michael Wojcik) wrote:
In article <ln************@nuthaus.mib.org>, Keith Thompson <ks***@mib.org>
writes:

Given "int zero = 0;", if you assume that all conversions are
performed at run time, it's difficult to imagine that (char*)0 and
(char*)zero could yield different results; it seems obvious that they
should be equivalent.


It's not obvious to me. (char*)0 is a null pointer constant, cast to
a char*. (char*)zero is an int variable value cast to char*. zero
is not a constant here, it does not meet the C99 definition of a null
pointer constant (as it is not an integer constant expression, nor
such an expression cast to void*), and operations on it need not obey
the null pointer constant rules in any fashion.


1. Conversion is implementation defined
2. Converting a null pointer constant produces a null pointer.

I interpret this as "The implementation defines what the result of
conversion from integer to pointer types is. However, it is not
completely free to do this in arbitrary ways: Whatever rules the
implementation chooses, it must make sure that these rules convert null
pointer constants to null pointers. "

The other IMO incorrect interpretation would be "The implementation
defines what the result of conversion from integer to pointer types is.
It is free to do so any way it likes. However, when the value converted
happens to be a null pointer constant, that definition is overridden,
and instead the result must be a null pointer."
Nov 14 '05 #82
Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
In article <cf*********@news3.newsguy.com>,
mw*****@newsguy.com (Michael Wojcik) wrote:
In article <ln************@nuthaus.mib.org>, Keith Thompson
<ks***@mib.org> writes:
Given "int zero = 0;", if you assume that all conversions are
performed at run time, it's difficult to imagine that (char*)0 and
(char*)zero could yield different results; it seems obvious that they
should be equivalent.


It's not obvious to me. (char*)0 is a null pointer constant, cast to
a char*. (char*)zero is an int variable value cast to char*. zero
is not a constant here, it does not meet the C99 definition of a null
pointer constant (as it is not an integer constant expression, nor
such an expression cast to void*), and operations on it need not obey
the null pointer constant rules in any fashion.


1. Conversion is implementation defined
2. Converting a null pointer constant produces a null pointer.

I interpret this as "The implementation defines what the result of
conversion from integer to pointer types is. However, it is not
completely free to do this in arbitrary ways: Whatever rules the
implementation chooses, it must make sure that these rules convert null
pointer constants to null pointers. "

The other IMO incorrect interpretation would be "The implementation
defines what the result of conversion from integer to pointer types is.
It is free to do so any way it likes. However, when the value converted
happens to be a null pointer constant, that definition is overridden,
and instead the result must be a null pointer."


That's a good description. I agree with it completely -- except for
the minor detail that the first interpretation is incorrect, and the
second one is correct. 8-)}

I think I'll ask about this in comp.std.c, where the *real* language
lawyers hang out.

--
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 #83
"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
I think I'll ask about this in comp.std.c, where the *real* language
lawyers hang out.


Holy Shit! There are worse ones than YOU!!! Well, what kind of chance does
that give the rest of us...

--
Mabden
Nov 14 '05 #84

"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote
This is because the lowest location in memory is always special in some
way,


You don't know that.

There is no inherent reason why it is impossible to engineer a system on
which location zero is just a normal memory location. However in practise
you always need some locations used for special purposes, and zero is always
chosen as one of those special locations.
Nov 14 '05 #85
"Malcolm" <ma*****@55bank.freeserve.co.uk> writes:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote
This is because the lowest location in memory is always special in some
way,
You don't know that.

There is no inherent reason why it is impossible to engineer a system on
which location zero is just a normal memory location.


Certainly.
However in practise
you always need some locations used for special purposes,
At least one (the null pointer value, whatever it is).
and zero is always
chosen as one of those special locations.


Always? I'm skeptical. Are you familiar enough with all existing
systems to be sure of that?

Several examples have been given on this thread of architectures where
address are represented as signed integers. On such a system, address
0 is right in the middle of the address space. (Admittedly, that
doesn't necessarily imply that it's not reserved, but I wouldn't bet
either way.)

If address all-bits-zero were always reserved on all systems, the C
standard might as well have mandated that a null pointer is always
represented as all-bits-zero. As we all know, it didn't.

But even if the all-bits-zero address happens to be reserved on all
past, present, and future systems, there's no reason for anyone
writing portable code to care. There is nothing you can portably do
with *any* specific address other than the null pointer (which of
course can vary from one system to another).

--
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 #86

"Keith Thompson" <ks***@mib.org> wrote in message
However in practise you always need some locations used for special
purposes,
At least one (the null pointer value, whatever it is).
and zero is always chosen as one of those special locations.


Always? I'm skeptical. Are you familiar enough with all existing
systems to be sure of that?

Several examples have been given on this thread of architectures where
address are represented as signed integers. On such a system, address
0 is right in the middle of the address space. (Admittedly, that
doesn't necessarily imply that it's not reserved, but I wouldn't bet
either way.)

You'd have to know absolutely every platform out there to be sure, and if
there is an exception it is probably a signed address system. I would still
be surprised if location zero is not chosen for some special use, because it
is perfectly natural to map code to above zero and data to below, or put
fast RAM below and slow RAM above. The only exception would be if you want
to allow huge objects taking up more than half your address space, in which
case the only way is to treat zero as an ordinary memory location.
If address all-bits-zero were always reserved on all systems, the C
standard might as well have mandated that a null pointer is always
represented as all-bits-zero. As we all know, it didn't.

The special feature might be that a value of all bits zero automatically
traps when loaded into an address register, so obviously this would be a
poor choice of value for the null pointer. Alternatively execution may
always start at 0, which might mean that a function pointer set to main
would be all bits zero.
Nov 14 '05 #87

In article <ch*********************************@slb-newsm1.svr.pol.co.uk>, Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
In article <cf*********@news3.newsguy.com>,
mw*****@newsguy.com (Michael Wojcik) wrote:
It's not obvious to me. (char*)0 is a null pointer constant, cast to
a char*. (char*)zero is an int variable value cast to char*. zero
is not a constant here...
1. Conversion is implementation defined
2. Converting a null pointer constant produces a null pointer.


Agreed.
I interpret this as "The implementation defines what the result of
conversion from integer to pointer types is. However, it is not
completely free to do this in arbitrary ways: Whatever rules the
implementation chooses, it must make sure that these rules convert null
pointer constants to null pointers. "


A plausible interpretation; however, "zero" in your example is not a
constant; hence it cannot be a null pointer constant (and indeed does
not meet the C99 definition of a null pointer constant); hence this
interpretation is irrelevant to the question at hand.

The null pointer constant rules need only apply to null pointer
constants, which are a special case of constants. And the standard
says nothing about converting non-constant integer expressions that
happen to have value 0.

--
Michael Wojcik mi************@microfocus.com

Do not "test" parts, as this may compromise sensitive joinery. Those who
suffer difficulty should abandon the enterprise immediately. -- Chris Ware
Nov 14 '05 #88

In article <cf**********@newsg3.svr.pol.co.uk>, "Malcolm" <ma*****@55bank.freeserve.co.uk> writes:

There is no inherent reason why it is impossible to engineer a system on
which location zero is just a normal memory location. However in practise
you always need some locations used for special purposes, and zero is always
chosen as one of those special locations.


Always? There has never been and will never be a system where address
0 isn't used for some special purpose? There are no embedded systems
which would permit the designer to put ordinary RAM at location 0?

I think you'll find you're wrong about that. A little Google searching
turned up a couple of memory maps with RAM banks starting at address 0.

--
Michael Wojcik mi************@microfocus.com

Recently, they appeared at the reopening of the Brookdale Library,
luring passersby with the opportunity to be anonymously silly.
Nov 14 '05 #89
Michael Wojcik wrote on 08/08/04 :
A little Google searching
turned up a couple of memory maps with RAM banks starting at address 0.


The x86 Intel architecture is a good example. The boot address it at
FFFF0 (FFFF:0000) and the RAM starts at 0 (0000:0000).

But the data from 0 are interrupt vectors. At boot time, the data from
0 is just other data. But they are reserved by Intel to implement the
interrupt vectors.

It's different on a 68k where the address 0 holds the boot vector. Must
be a *ROM, not a RAM.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html

"C is a sharp tool"

Nov 14 '05 #90
In article <ch*********************************@slb-newsm1.svr.pol.co.uk>,
Christian Bau <ch***********@cbau.freeserve.co.uk> wrote:
1. Conversion is implementation defined
2. Converting a null pointer constant produces a null pointer.

I interpret this as "The implementation defines what the result of
conversion from integer to pointer types is. However, it is not
completely free to do this in arbitrary ways: Whatever rules the
implementation chooses, it must make sure that these rules convert null
pointer constants to null pointers. "


Your argument relies on the assumption that the implementation-defined
conversion must return the same result for a null pointer constant as
for non-constant zeros. Can you show that from the standard?

After all, if the standard's own definition of the conversion of
integers to pointers can make use of this distinction, why can't
the implementation's?

-- Richard
Nov 14 '05 #91
Emmanuel Delahaye wrote:
.... snip ...
It's different on a 68k where the address 0 holds the boot vector.
Must be a *ROM, not a RAM.


That does not necessarily follow. An 8080 starts execution at 0,
but that address also normally holds an interrupt vector. My
solution was to have the power on reset set a circuit which jammed
the high order address byte (from a dipswitch) onto the buss for
the first 3 cycles. Now I could set an initializing ROM anywhere
on 256 byte intervals, as long as the first instruction was a jmp
absolute.

--
"Churchill and Bush can both be considered wartime leaders, just
as Secretariat and Mr Ed were both horses." - James Rhodes.
"A man who is right every time is not likely to do very much."
- Francis Crick, co-discover of DNA
Nov 14 '05 #92
Christian Bau <ch***********@cbau.freeserve.co.uk> wrote:
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
(char*)0 --> $12345678$ (null pointer)
int zero = 0;
(char*)zero --> $00000000$ (non-null pointer)
(char*)0x12345678 --> $12345678$ (happens to be a null pointer)


Quite possible in C90, but most definitely not in C99. In C90, the
wording was such that in an assignment, or within an equality operator,
and probably some cases that I forgot, a null pointer constant was
replaced with a null pointer. (char*)0 was _not_ one if these cases and
in C90 not guaranteed to be a null pointer; in C99 they added that
_every_ conversion of a null pointer constant to a pointer produces a
null pointer.


Ok, but whatever makes you think that (char *)zero involves a null
pointer constant? A null pointer constant is not an integer expression,
it is an integer _constant_ expression.

Richard
Nov 14 '05 #93
"Malcolm" <ma*****@55bank.freeserve.co.uk> writes:
"Keith Thompson" <ks***@mib.org> wrote in message

[...]
If address all-bits-zero were always reserved on all systems, the C
standard might as well have mandated that a null pointer is always
represented as all-bits-zero. As we all know, it didn't.

The special feature might be that a value of all bits zero automatically
traps when loaded into an address register, so obviously this would be a
poor choice of value for the null pointer. Alternatively execution may
always start at 0, which might mean that a function pointer set to main
would be all bits zero.


Depending on the details of the architecture, trapping on loading
all-bits-zero into an address register might be a good argument in
favor of using all-bits-zero for the null pointer, assuming that
legitimate operations on a null pointer (such as assignment and
equality comparison) can be done without loading it into an address
register.

But you're right; even if all-bits-zero were always reserved on all
systems, that wouldn't necessarily mean it's always a good idea to use
all-bits-zero as the null pointer.

But I still maintain that we can't assume (and, more importantly,
shouldn't care) that all-bits-zero is always reserved on all systems.
Even if it is, there's nothing useful we can do with that information.

--
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 #94

"Michael Wojcik" <mw*****@newsguy.com> wrote

Always? There has never been and will never be a system where address
0 isn't used for some special purpose? There are no embedded systems
which would permit the designer to put ordinary RAM at location 0?

I think you'll find you're wrong about that. A little Google searching
turned up a couple of memory maps with RAM banks starting at address 0.

The "system" is the hardware plus the C compiler. If the hardware doesn't
use all bits zero for something special the C compiler probably will, often
for the null pointer but maybe just as a control block for the beginning of
the heap or something similar.
Nov 14 '05 #95
"Malcolm" <ma*****@55bank.freeserve.co.uk> writes:
"Michael Wojcik" <mw*****@newsguy.com> wrote
Always? There has never been and will never be a system where address
0 isn't used for some special purpose? There are no embedded systems
which would permit the designer to put ordinary RAM at location 0?

I think you'll find you're wrong about that. A little Google searching
turned up a couple of memory maps with RAM banks starting at address 0.

The "system" is the hardware plus the C compiler. If the hardware doesn't
use all bits zero for something special the C compiler probably will, often
for the null pointer but maybe just as a control block for the beginning of
the heap or something similar.


If you're arguing that the all-bits-zero address is *usually* reserved
for something special (whether for the null pointer for for something
else), I completely agree.

If you're arguing, as I think you have been, that it's *always*
reserved, I suspect you're mistaken, but it doesn't really matter one
way or the other. It's not always reserved for the same thing on
different systems, so the assumption that it's always reserved doesn't
lead to any useful conclusions.

If you're arguing that it *should* always be reserved, I strongly
disagree. There's no point in imposing this kind of restriction.

--
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 #96

In article <cf**********@news6.svr.pol.co.uk>, "Malcolm" <ma*****@55bank.freeserve.co.uk> writes:

"Michael Wojcik" <mw*****@newsguy.com> wrote

Always? There has never been and will never be a system where address
0 isn't used for some special purpose? There are no embedded systems
which would permit the designer to put ordinary RAM at location 0?

The "system" is the hardware plus the C compiler. If the hardware doesn't
use all bits zero for something special the C compiler probably will, often
for the null pointer but maybe just as a control block for the beginning of
the heap or something similar.


You claimed address 0 was *always* reserved. This "probably" is just
weaseling out.

And yes, I think this *is* important here. Some people like to make
pronouncements on c.l.c of the form "X isn't guaranteed by the
standard, but in practice it's always true". That sort of thing
leads to bad practice. I've known plenty of C programmers who think
that in practice the alpha characters are contiguous (in a single
case), but anyone who's had to port C to an EBCDIC machine, as I
have, knows that's not the case, and that there's plenty of code
which breaks on EBCDIC systems because of such assumptions.

It is rarely a good idea to declare that something is always true in
C, if it's not specified that way by the standard. And in a case
like this it wouldn't be useful anyway if it were true. So why make
that claim? It's more useful to be precise and say, "look, don't
count on it; write your code correctly".

--
Michael Wojcik mi************@microfocus.com

Push up the bottom with your finger, it will puffy and makes stand up.
-- instructions for "swan" from an origami kit
Nov 14 '05 #97

"Michael Wojcik" <mw*****@newsguy.com> wrote

You claimed address 0 was *always* reserved. This "probably" is just
weaseling out.
No one has posted a counter example, which strongly suggests that there
isn't one.
And yes, I think this *is* important here. Some people like to make
pronouncements on c.l.c of the form "X isn't guaranteed by the
standard, but in practice it's always true". That sort of thing
leads to bad practice.
But also helps understanding. If a newbie thinks that something is likely
which he will never in fact encounter, that causes confusions. Humans are
not natural lawyers who can learn a rule divorced from practical examples.
I've known plenty of C programmers who think
that in practice the alpha characters are contiguous (in a single
case), but anyone who's had to port C to an EBCDIC machine, as I
have, knows that's not the case, and that there's plenty of code
which breaks on EBCDIC systems because of such assumptions.

A lot of code is like that. For instance IFF files have 4-byte ASCII
identifiers. It is natural to write if(!strcmp(tag, "HEAD")), but of course
this will break on non-ASCII machines. It is rarely much of a problem since
in most environments you can assume ASCII. If you put the ASCII codes in the
tag would become unreadable.
Nov 14 '05 #98
"Malcolm" <ma*****@55bank.freeserve.co.uk> writes:
"Michael Wojcik" <mw*****@newsguy.com> wrote

You claimed address 0 was *always* reserved. This "probably" is just
weaseling out.

No one has posted a counter example, which strongly suggests that there
isn't one.


Maybe, but so what? There is nothing to be gained by assuming that
address all-bits-zero is always reserved.

I'd be willing to bet (but not much) that no real-world system will
have a C object at address all-bits-one, but that's no more or less
useful.

There can be some benefit, I suppose, in knowing that the
all-bits-zero address is *probably* reserved for something, even on a
system where a null pointer has some other representation. If you
examine a pointer variable in a debugger (or display it with printf's
"%p" format, depending on how that works), you see that its value is
all-bits-zero, and you happen to know that a null pointer isn't
all-bits-zero on the current system, then it's likely that something
has gone wrong. But if you're doing that kind of low-level
examination of pointer representations, you really should know
something about the system you're working on without reference to any
hypothetical univeral principle about all-bits-zero pointers. That
kind of system-specific knowledge is very different from your original
claim, that the all-bits-zero address is *always* reserved (for
something or other) on all systems.

--
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 #99
On Tue, 10 Aug 2004 20:24:19 +0100
"Malcolm" <ma*****@55bank.freeserve.co.uk> wrote:

"Michael Wojcik" <mw*****@newsguy.com> wrote

You claimed address 0 was *always* reserved. This "probably" is
just weaseling out.
No one has posted a counter example, which strongly suggests that
there isn't one.


I've used embedded systems where it was ordinary RAM from location 0.
These were embedded systems designed with RAM at the bottom of the
memory map and ROM at the top because that was the simplest way to do
it. In such circumstances it would definitely make sense to have NULL as
being something other than all bits zero to avoid wasting a location.
And yes, I think this *is* important here. Some people like to make
pronouncements on c.l.c of the form "X isn't guaranteed by the
standard, but in practice it's always true". That sort of thing
leads to bad practice.

But also helps understanding. If a newbie thinks that something is
likely which he will never in fact encounter, that causes confusions.
Humans are not natural lawyers who can learn a rule divorced from
practical examples.


To be a good programmer you have to learn to understand and work with
abstractions, which is all you have to think of NULL, the null pointer
constant and null pointers as being. They are all just ways of
representing a guaranteed invalid pointer value.

You also have to learn to accept that some things which are incorrect
will work 99.9% of the time, but the time they fail is almost certainly
going to be the worst possible time for you.
I've known plenty of C programmers who think
that in practice the alpha characters are contiguous (in a single
case), but anyone who's had to port C to an EBCDIC machine, as I
have, knows that's not the case, and that there's plenty of code
which breaks on EBCDIC systems because of such assumptions.

A lot of code is like that. For instance IFF files have 4-byte ASCII
identifiers. It is natural to write if(!strcmp(tag, "HEAD")), but of
course this will break on non-ASCII machines.


No, you write something like:
if(!strcmp(tag, IFF_HEAD_TAG))

with a #define in an appropriate header.
It is rarely much of a
problem since in most environments you can assume ASCII. If you put
the ASCII codes in the tag would become unreadable.


If you look at the Chinese character sets you might find this is not
true. Also, if you look at, for example, the character sets as used by
Germans you will find than not all characters counted as letters are
in the caught by:
if ((ch>= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
since you have various accented letters.
--
Flash Gordon
Sometimes I think shooting would be far too good for some people.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #100

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
by: mike79 | last post by:
Hi all, I have a the following simple piece of code which has taken me hours to try and sort out the problem, but still unable to find what is wrong. void main( void ) { char (*string);...
29
by: Jason Curl | last post by:
I've been reading this newsgroup for some time and now I am thoroughly confused over what NULL means. I've read a NULL pointer is zero (or zero typecast as a void pointer), others say it's...
41
by: Alexei A. Frounze | last post by:
Seems like, to make sure that a pointer doesn't point to an object/function, NULL (or simply 0) is good enough for both kind of pointers, data pointers and function pointers as per 6.3.2.3: 3 An...
16
by: Abhishek | last post by:
why do I see that in most C programs, pointers in functions are accepted as: int func(int i,(void *)p) where p is a pointer or an address which is passed from the place where it is called. what...
64
by: yossi.kreinin | last post by:
Hi! There is a system where 0x0 is a valid address, but 0xffffffff isn't. How can null pointers be treated by a compiler (besides the typical "solution" of still using 0x0 for "null")? -...
69
by: fieldfallow | last post by:
Hello all, Before stating my question, I should mention that I'm fairly new to C. Now, I attempted a small demo that prints out the values of C's numeric types, both uninitialised and after...
11
by: Johs32 | last post by:
If I have a pointer and initialize it to NULL does it have the same effect if I initialize it to 0 instead, no matter what kind of pointer it is?
12
by: p.lavarre | last post by:
Q: The C idea of (pv != NULL) is said most directly in Python ctypes how? A: We are of course supposed to write something like: def c_not_null(pv): return (ctypes.cast(pv,...
76
by: valentin tihomirov | last post by:
As explained in "Using pointers vs. references" http://groups.google.ee/group/borland.public.delphi.objectpascal/browse_thread/thread/683c30f161fc1e9c/ab294c7b02e8faca#ab294c7b02e8faca , the...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.