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.....
> Can 0x0 be a valid virtual address in the address space
> of an application ?
Yes.
> 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.
No. If 0 is a valid (C-accessible) address on the machine, then
0 is not a legal representation for a pointer value.
> Then how can i distinguish between a NULL pointer and an invalid
> location ?
The null (not NULL) pointer tests equal to a integer constant
expression with value 0. Invalid locations don't.
> Is this essential that NULL pointer should not point to any of
> the location in the virtual address space ?
It's essential that the null (not NULL) pointer not point to
any C-accessible location.
> 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 ?
NULL has nothing to do with location 0 (except by coincidence on
most machines). You're confusing the internal representation of
the null pointer with the internal representation of the integer
0 - and the implementation is free to use some *other* representaion
of the null pointer, such as the address of some byte in the run-time
system that no C program can legally see.
> 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 ?
No. That's nice, but it's not required.
> 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.....
Don't try and understand what's implemented; try and understand
the rules.
--
Chris "electric hedgehog" Dollin
C FAQs at: http://www.faqs.org/faqs/by-newsgroup/comp/comp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html
>Can 0x0 be a valid virtual address in the address space
>of an application ?
Historically, and in almost all C implementations, null pointers are
just pointers corresponding to the address 0. In these
implementations, if you put the integer zero into a location whose
size is the same as a pointer, and then treat that location as a
pointer, you will be doing exactly the same thing as if you had a real
null pointer.
The C standards don't require things to work like that though. They
make null pointers more abstract, like nil in Lisp or null in Java.
Null pointers *could* be represented so that they corresponded to the
address 0x12345678. In that case, the implementation would have to be
careful never to put a real object at address 0x12345678, and an
assignment like "int *foo = 0" or "int *foo = NULL" would have to be
compile to code that put the value 0x12345678 into foo's location.
Setting the location to zero by some means such as memset or calloc
would not work.
All this is quite separate from whether dereferencing a null pointer
causes some kind of exception. On modern machines with virtual memory
it's usual to unmap that page containing the null pointer address
(which in practice is page 0 - an implementation that represented null
pointers as 0x12345678 could unmap that page instead). This wasn't
always the case: a lot of early Vax C code assumed that null pointers
pointed to a byte containing zero, so that null pointers and empty
strings were interchangable. This practice was eradicated once people
ported their programs to machines like the early Suns, which did unmap
page 0.
-- Richard
No. Zero is never a valid location in C.
--
Mabden
It's not a valid pointer value, but it can be a valid memory address. As
has been stated, pointer values need not correspond exactly to memory
addresses.
--
/-- Joona Palaste (pal...@cc.helsinki.fi) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
It depends on what you mean by "valid".
(I'm going to use the term "all-bits-zero" to refer to memory address
zero, since a literal 0 can refer to some other address.)
If an implementation's representation of a null pointer is
all-bits-zero, no C object (either declared or allocated via malloc())
can exist at that address. Any attempt to dereference a null pointer
invokes undefined behavior. However, it's entirely possible (for a
given implementation) that there is an addressible memory location at
address all-bits-zero, and that a C program is able to access it
by dereferencing a null pointer.
Dereferencing a null pointer invokes undefined behavior; that can
include fetching a value stored at address all-bits-zero, trapping, or
making demons fly out your nose.
An implementation is obliged not to store a visible C object at the
address it reserves for null pointers; it's not obliged to trap
attempts to dereference a null pointer.
(Actually that's not quite true; there could be a visible object
named, say, __FOO__ at the null address, perhaps wit the specific
purpose of preventing any other object from occupying that address.
I don't know of any implementation that actually does this.)
To the OP: read sections 4 and 5 of the C FAQ if you haven't already.
--
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.
Chapter and verse? AFAIK there are several architectures where
zero is a valid location, and you can safely read and write from it.
Yes.
>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.
The declaration:
or
char *p = 0;
is not guaranteed to put the bit pattern 0xdeadbeef into p, even
on 32-bit machines, or the pattern 0xdeadbeef0xdeadbeef on 64-bit
machines. But it might.
>Then how can i distinguish between a NULL pointer and an invalid
>location ?
The code:
if (p == 0) { ... } /* integer constant zero */
or
if (p == NULL) { ... } /* integer constant zero */
might generate the assembly code:
cmpl r4,#0xdeadbeef (Compare p with the bit pattern deadbeef)
bne .L5
...
.L5:
While the code:
int i = 0;
if (p == i) { ... } /* i is *NOT* an integer constant zero */
might gnerate the assembly code:
cmpl r4, #0 (Compare p with the bit pattern 00000000 )
bne .L5
...
.L5:
>Is this essential that NULL pointer should not point to any of
>the location in the virtual address space ?
Lots of older implementations without virtual memory used a NULL
pointer bit pattern of all-bits-zero and address 0 was a valid
address in the virtual address space (e.g. you could read, and even
write, it without having anything nasty happen like SIGSEGV.)
However, the thing at address was NOT a valid C object. Sometimes
it was startup code. Sometimes it was a zero byte, so code like:
printf("%s", NULL);
wouldn't print garbage, and also to prevent address 0 from being
assigned as a valid C object. I prefer the implementation where
the above printf() produces a list of cusswords.
>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 ?
If you (a compiler writer) use a NULL pointer value of all-bits-zero,
you don't have to be so careful about translating "an integer
constant with value 0 in a pointer context" to a NULL pointer
representation with a different bit pattern. This takes care in
writing the compiler, it may make code slightly bigger and slower,
and it causes bogus bug reports from people trying to compile sloppy
code. And in assembly language, testing for zero is likely to be
faster. Probably most important, making the NULL pointer all-bits-zero
lets crap code (there's a LOT of it out there!) run and cuts down
on your tech support costs.
>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 ?
No. But it's a really, really good idea. So is deleting the
offending source code (all copies), but I haven't seen anyone do
that yet. And an application should be coded assuming that it
*MIGHT* be aborted if it does that.
>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.....
Ignore the documents written by any US political party about
NULL pointers. They are just trying to drum up support to
tax them. And don't bid on any null pointers for sale on Ebay.
Gordon L. Burditt
char *ptr = 0;
*ptr = 1;
it may segfault, or it may write the value 1 to location 0 in memory, or it
may cause little green eleves to appear on screen.
This code is OK
void foo(char *ptr)
{
assert(ptr != 0);
}
char ch;
foo(&ch);
as long as ch is a valid object, the address may never evaluate to 0 (NULL).
This code is implementation defined
int x = 0;
char *ptr = (char *) x;
*ptr = 1;
if your platform allows writes to a location represented by all bits zero,
then it is correct. However most platforms won't allow this.
No, actually several common desk top operating systems that you happen
to be familiar with do not allow this. Unfortunately your desk top
chauvinism is totally incorrect as far as the vast majority of
platforms that run C is concerned.
On most processors, microcontrollers, and DSPs, that have C
implementations, which number orders of magnitude more than your desk
top platforms, you can access memory at address "all bits 0". Whether
there is any utility to doing so, and what might happen if you try to
write there, is another story. But a read access is totally benign,
the memory location exists, and the result is whatever it contains.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
Er .. did't you just say the same thing Malcolm said? Or am I reading
you wrong?
> On most processors, microcontrollers, and DSPs, that have C
> implementations, which number orders of magnitude more than your desk
> top platforms, you can access memory at address "all bits 0". Whether
> there is any utility to doing so, and what might happen if you try to
> write there, is another story. But a read access is totally benign,
> the memory location exists, and the result is whatever it contains.
>
True; there are also machines where all-bits-0 is an invalid address,
and even machines (extinct, to my knowledge) where very low addresses
(including all-bits-0) represented actual register locations. However,
on all of these machines, it is _still_ up to the compiler to map a
constant 0 value to the NULL address (however it may be represented
internally).
Cheers,
Ron
--
Ron Collins
K&R2 pg. 102 "C guarantees that zero is never a valid address for data..."
--
Mabden
My copy of K&R2 isn't handy, but I presume "zero" refers to a null
pointer (which can be represented in source by a literal 0), not
necessarily to an all-bits-zero address.
thanx a lot to all of you for the valuable comments and help....
That would make a "pres" out of "u" and "me".
It refers to a location. There is no location zero in memory in C for data.
Where the hell is Dan Pop?!! Back me up, Dude.
--
Mabden
You must be very brave to utter his name.
> > Where the hell is Dan Pop?!! Back me up, Dude.
>
> You must be very brave to utter his name.
I don't know why he keeps saying that. I explained all this to him once
on CLC++, but the message didn't get across.
He needs to engage his brain.
Brian Rodenborn
>
>"Old Wolf" <old...@inspire.net.nz> wrote
>>
>> > No. Zero is never a valid location in C.
>>
>> Chapter and verse? AFAIK there are several architectures where
>> zero is a valid location, and you can safely read and write from it.
>>
>This code is undefined
>
>char *ptr = 0;
>
>*ptr = 1;
>
<snip>
This is only because 0 is converted to the internal value for
representing a NULL-pointer, isn't it?
Hmm let's see, how could we...
char *ptr = 0; /* ptr is a NULL pointer */
char **p = &ptr;
*p ^= *p; /* I am hoping to have cleared every bit of ptr */
If every bit of ptr is cleared and it has the value '0', it is no
longer necessarily a NULL pointer, is it?
--
aib
ISP e-mail accounts are good for receiving spam.
K&R2 is not the standard. It does not specify the C language. It
describes it with considerable fidelity, but not perfectly; it
contains errors.[1]
> > My copy of K&R2 isn't handy, but I presume "zero" refers to a null
> > pointer (which can be represented in source by a literal 0), not
> > necessarily to an all-bits-zero address.
It's not K&R's finest moment. Here's a bit more context:
If not, alloc must return some signal that no space is left. C
guarantees that zero is never a valid address for data, so a return
value of zero can be used to signal an abnormal event, in this case,
no space.
From the context it's clear that in this instance they're referring to
a pointer value - what's returned by their alloc() function. However,
the text fails to make clear that this does not apply to the actual
internal representation of an address. The use of "address" here is
infelicitous - it's either wrong or misleading. IMO this should be
added to the errata list.
> That would make a "pres" out of "u" and "me".
> It refers to a location. There is no location zero in memory in C for data.
Either the text is incorrect or you are misreading it. It's not
clear from the text itself which is the case. (If Dennis is reading
this thread, maybe he'll tell us what the intent of this sentence was.)
In C, *there is no relationship between a pointer value and the address
to which it refers*. In every C implementation, of course, there must
be some such relationship - but it certainly need not be as simple as
"pointer value is an address". There are extant conforming C implemen-
tations where that is not the case. And so while a pointer value of 0
must not refer to the location of any object in C, an object can exist
at address 0. A pointer to that object will not have value 0; that is
all.
1. http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html
--
Michael Wojcik michael...@microfocus.com
Painful lark, labouring to rise!
The solemn mallet says:
In the grave's slot
he lies. We rot. -- Basil Bunting
Right. (It's more accurate to say "null pointer"; NULL is a macro
that expands to a "null pointer constant", and it exists only in
source.)
> Hmm let's see, how could we...
>
> char *ptr = 0; /* ptr is a NULL pointer */
Right.
> char **p = &ptr;
>
> *p ^= *p; /* I am hoping to have cleared every bit of ptr */
There's not much point in creating something that points to ptr. The
above might as well be written as:
char *ptr = 0;
p ^= p; /* illegal */
but that's still incorrect. You can't apply the bitwise xor operator
to a pointer.
> If every bit of ptr is cleared and it has the value '0', it is no
> longer necessarily a NULL pointer, is it?
Correct (though it will be on many implementations).
Here's a cleaner way to do what you're trying to do:
#include <string.h>
...
char *ptr = 0;
/*
* ptr is a null pointer
*/
memset(&ptr, 0, sizeof(ptr));
/*
* ptr is all-bits-zero; it may or may not be a null pointer
*/
(*p) is an expression of type pointer to char.
Bitwise operations are undefined on pointer types.
int main(void)
{
char *ptr = 0;/* ptr is a null pointer */
size_t n = sizeof ptr;
while (n--) {
((unsigned char*)&ptr)[n] = 0;
}
/*
** The bits of ptr are cleared and it's value is undefined,
** it is no longer necessarily a null pointer.
*/
return 0;
}
--
pete
Fools are always brave; it goes with the territory. And Brian assures me I
am a fool (thanks for that Brian, I think the world of your people skills
and I'm sure you have many loving friends).
<engaging brain, opening mouth, foot at the ready...>
So, you are saying that (on some mythical machine) I could have an array a[]
that lives at location 0000:0000 of memory and point to it with ptr = &a and
ptr would not be a NULL pointer? I'm not sure I can get behind that. If
nothing else, the compiler (or linker or loader, whatever) should disallow
storing at memory location 0.
Also, you are saying that 0 can live anywhere in memory and ptr = 0 (as in
char *ptr = 0) would be NULL. This part I get, and agree with.
<disengaging overheated gears, cooling with beer>
--
Mabden
Mabden wrote:
> "Default User" <first...@boeing.com.invalid> wrote in message
> news:411109F4...@boeing.com.invalid...
>
>>Keith Thompson wrote:
>>
>>>"Mabden" <mabden@sbc_global.net> writes:
>>
>>>>Where the hell is Dan Pop?!! Back me up, Dude.
>>>
>>>You must be very brave to utter his name.
>>
>>
>>I don't know why he keeps saying that. I explained all this to him once
>>on CLC++, but the message didn't get across.
>>
>>He needs to engage his brain.
>>
>>Brian Rodenborn
>
>
> Fools are always brave; it goes with the territory. And Brian assures me I
> am a fool (thanks for that Brian, I think the world of your people skills
> and I'm sure you have many loving friends).
>
> <engaging brain, opening mouth, foot at the ready...>
> So, you are saying that (on some mythical machine) I could have an array a[]
> that lives at location 0000:0000 of memory and point to it with ptr = &a and
> ptr would not be a NULL pointer? I'm not sure I can get behind that. If
However, it is correct. On some machines, physical address 0 is a valid
memory location (IIRC, the old CSC machines used lower addresses
(including 0) to access the registers). However, the compiler is
required to map a *constant* 0 value to the NULL pointer. (Even if the
mapping stores a completely different bit pattern into the pointer
variable.
> nothing else, the compiler (or linker or loader, whatever) should disallow
> storing at memory location 0.
The compiler will handle mapping the "address" you store into a pointer
into actual physical memory addresses. There is no requirement that the
value you "see" in your source code is the actual physical memory
address used by the operating system. Think of old DOS segmented memory
addresses where there were several (in-code) representations for a
single physical memory address.
>
> Also, you are saying that 0 can live anywhere in memory and ptr = 0 (as in
> char *ptr = 0) would be NULL. This part I get, and agree with.
> <disengaging overheated gears, cooling with beer>
>
Cheers,
Ron
--
Ron Collins
Air Defense/RTSC/BCS
"I have a plan so cunning, you could put a tail on it and call it a weasle"
Yes (but please use the phrase "null pointer", not "NULL pointer";
NULL is a macro). I'm assuming that your 0000:0000 notation refers to
an all-bits-zero representation.
> I'm not sure I can get behind that. If nothing else, the compiler
> (or linker or loader, whatever) should disallow storing at memory
> location 0.
Why should it?
Despite what K&R2 says on page 102, C says nothing special about an
all-bits-zero address. The only special address defined by the
language is the null pointer, which may or may not be represented as
all-bits-zero. (The wording in K&R2, as far as I can tell, is
consistent with a requirement that null pointers always being
represented as all-bits-zero. The standard itself is not, though of
course a given implementation is allowed to represent null pointers as
all-bits-zero if it chooses).
> Also, you are saying that 0 can live anywhere in memory and ptr = 0 (as in
> char *ptr = 0) would be NULL. This part I get, and agree with.
> <disengaging overheated gears, cooling with beer>
0 is a null pointer constant, as is any integer constant expression
with the value 0, or such an expression cast to void*. Converting a
null pointer constant to any pointer type yields a null pointer, which
is guaranteed to compare unequal to a pointer to any object or
function.
In my opinion, the standard isn't quite as clear as it should be about
things that occur in source vs. things that exist at run time. A
"null pointer constant" is a construct that appears only in C source,
and is interpreted by the compiler. NULL is a macro that expands to a
null pointer constant; again, it appears only in C source. A "null
pointer" is a particular pointer value that can exist when a program
is running (and the source may no longer even exist).
Here's something that might clarify things a bit (or not).
Suppose you're designing a programming language. You need a distinct
pointer value that doesn't point to any object, to be used for things
like indicating that a memory allocation failed, marking the end of a
linked list, etc. Call this value a "nil pointer". You don't want
programmers to care how a "nil pointer" is represented (it might be
0xdeadbeef on one platform, 0xffffffff on another), so you have a
keyword "nil" to represent a nil pointer value:
//
// This is not C.
//
char *ptr = malloc(42);
if (ptr == nil) printf("malloc failed\n");
You can think of the keyword "nil" as a "nil pointer constant".
Now you have a nice clean language. Pointers and integers are two
entirely separate things, and there's no reason anyone should confuse
"nil" (a pointer value) with "zero" (an integer value).
Now you get some feedback from your customers. They complain that
"nil" takes too long to type; they want to use a literal 0 to indicate
a nil pointer value. You give in to their demands. But is "0"
equivalent to "1-1" or "0x0"? It turns out that the cleanest way to
make this work is to say that any integer constant expression with the
value 0, or such an expression cast to void*, is a "nil pointer
constant" (in addition to the existing "nil" keyword).
You release the new language specification, but there are still
complaints. Users don't want "nil" to be a keyword, since they want
to use it as an identifier. So in the next revision of your language,
you remove the "nil" keyword; a "nil pointer constant" is *just* an
integer constant expression with the value 0, or such an expression
cast to void*. You grumble that the users' complaints have messed up
your nice clean design; there'll probably need to be an entire section
in the FAQ just to explain this. And while you're at it, you change
the terminology a bit: "nil pointer" becomes "null pointer", and "nil
pointer constant" becomes "null pointer constant". And you add a NULL
macro that expands to a null pointer constant.
And now your new language is C.
(Incidentally, this is not how C actually evolved. There never was a
"nil" keyword; I'm fairly sure the use of 0 as a null pointer constant
goes back to the beginning, if not farther.)
What has that got to do with the location zero?
When you assign '0' to a pointer in C, you get a null pointer,
not a pointer to the location zero. (Of course, on some architectures
those two things are the same, but many architectures are different).
That is what I mean, yes, as it was a popular notion in Windows programming
denoting segment:offset. I will use "null" to mean location 0 in memory
(0000:0000, or 0:0 for short), as in the very first addressable location
possible on the machine.
NULL is a macro, I agree, for basically (char *)0. This would be a zero
somewhere in memory that the program stores upon startup and compares
various pointers to, so if NULL happens to point to 1234:4321, and I set
"ptr1 = ptr2 = NULL" then both pointers would point to 1234:4321. Any
allocation or function that returns NULL would be passing the address
1234:4321, and the program would consider that to mean the allocation
failed, or the pointer has not been initialized.
I think these things are distinct cases. 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. When I state that belief, I
sometimes get told I am wrong. I only have the K&R to go on. I do not own
any reference to the "Standard this that or the other". But, didn't the K&R
come first? To make a religious reference, there was a Bible, then a New
Testament, then the Book of Mormon. I feel like I am looking at the Bible,
and getting quotes from the Book of Mormon telling me I'm wrong. "We have a
new way of doing it now!" "You aren't up to the new standard..." But I sit
back and look at MY gospel, and say, "Know, you are wrong! And your standard
is wrong if you are telling me the truth about what it says."
If the new standard says that location 0:0 is available for data storage,
then it is your standard that is wrong. Any insults to my character
nonwithstanding, that is "the way it was" and I think should be "the way it
is". It matters not at all how many people in a room decided differently.
0:0 is the true null pointer - nothing may be stored or removed from 0:0.
> > I'm not sure I can get behind that. If nothing else, the compiler
> > (or linker or loader, whatever) should disallow storing at memory
> > location 0.
>
> Why should it?
Because it is the law. Why can't you travel at the speed of light?
> Despite what K&R2 says on page 102, C says nothing special about an
> all-bits-zero address. The only special address defined by the
> language is the null pointer, which may or may not be represented as
> all-bits-zero. (The wording in K&R2, as far as I can tell, is
> consistent with a requirement that null pointers always being
> represented as all-bits-zero. The standard itself is not, though of
> course a given implementation is allowed to represent null pointers as
> all-bits-zero if it chooses).
See above.
> In my opinion, the standard isn't quite as clear as it should be about
> things that occur in source vs. things that exist at run time. A
> "null pointer constant" is a construct that appears only in C source,
> and is interpreted by the compiler. NULL is a macro that expands to a
> null pointer constant; again, it appears only in C source. A "null
> pointer" is a particular pointer value that can exist when a program
> is running (and the source may no longer even exist).
And my point is that the one, true null pointer, regardless of hardware is
location 0:0 in memory on whatever architechure you use. The NULL macro may
be implementation dependant, but C _guarantees_ that if you point a pointer
at location 0:0, you are pointing at an invalid location, and no reading or
writing is allowed. It is the "Ultimate Null". Praise Zero!
> Here's something that might clarify things a bit (or not).
Not.
--
Mabden
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?
(although i was trying to compare with some valid location)
Or i should never use hard coded address values except NULL
for pointer comparisons ?
> 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?
> (although i was trying to compare with some valid location)
> Or i should never use hard coded address values except NULL
> for pointer comparisons ?
How do you do that comparison?
Let's say you write
char* p = malloc (100);
and the call succeeds. "p == NULL" and "p == 0" will both be false.
However, it can be true that all the bits in p are zero on this
implementation.
If you write
int i = 0;
char* q = (char *) i;
then the C99 Standard guarantees that q is a null pointer. On this
implementation it means q will point to address 0x12345678 and it will
not be equal to p. Unlike most current compilers, a compiler for this
implementation will have to produce real code to cast from int to char*.
If int and char* have the same size and alignment, then you could try to
write
* (int *) &q = 0;
to set q to a null pointer. This will work on many implementations but
not on this one; it is indeed undefined behavior.
C uses the term "null pointer" with a very specific meaning. It is,
among other things, the value returned by a failing malloc() and the
value of of argv[argc]. It is not, I repeat not, necessarily
represented as all-bits-zero (though it can be and often is).
In the context of the C programming language, using the term "null" to
refer to an all-bits-zero address is only going to cause confusion.
> NULL is a macro, I agree, for basically (char *)0.
Not quite. NULL expands to an an implementation-defined null pointer
constant (C99 7.17p3). A null pointer constant is an integer constant
expression with the value 0, or such an expression cast to type void*
(C99 6.3.2.2p3). (NULL was probably defined as (char*)0 on some
pre-ANSI implementations, but that's invalid in current C.)
> This would be a zero somewhere in memory that the program stores
> upon startup and compares various pointers to, so if NULL happens to
> point to 1234:4321, and I set "ptr1 = ptr2 = NULL" then both
> pointers would point to 1234:4321. Any allocation or function that
> returns NULL would be passing the address 1234:4321, and the program
> would consider that to mean the allocation failed, or the pointer
> has not been initialized.
I'd say that the phrase "a zero somewhere in memory" is a bit
misleading, and there's nothing that's necessarily stored upon
startup, but that's basically correct.
> I think these things are distinct cases. 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. When I state
> that belief, I sometimes get told I am wrong. I only have the K&R to
> go on. I do not own any reference to the "Standard this that or the
> other". But, didn't the K&R come first? To make a religious
> reference, there was a Bible, then a New Testament, then the Book of
> Mormon. I feel like I am looking at the Bible, and getting quotes
> from the Book of Mormon telling me I'm wrong. "We have a new way of
> doing it now!" "You aren't up to the new standard..." But I sit back
> and look at MY gospel, and say, "Know, you are wrong! And your
> standard is wrong if you are telling me the truth about what it
> says."
Sorry, but the language really is defined by the ISO standard.
(There's some dispute about whether the C90 or C99 standard is
currently more important, but they're consistent with each other in
this particular area.) If K&R2 conflicts with the standard, K&R2 is
in error. This isn't a religious issue; Kernighan and Ritchie
themselves would tell you the same thing. Take a look at the errata
list at <http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html>.
My copy of K&R2 isn't handy at the moment, but I was looking at it
earlier today. The text on page 102 is a tutorial, not a reference.
There is a language reference in Appendix A. Look up "null pointer
constant" in the index. Read the section of Appendix A that discusses
null pointer constants. It does not say anything about an
all-bits-zero address.
> If the new standard says that location 0:0 is available for data storage,
> then it is your standard that is wrong. Any insults to my character
> nonwithstanding, that is "the way it was" and I think should be "the way it
> is". It matters not at all how many people in a room decided differently.
> 0:0 is the true null pointer - nothing may be stored or removed from 0:0.
I don't recall insulting your character; if I did, it was unintentional.
An implementation in which the all-bits-zero address is available for
data storage can be (and in which a null pointer is represented as,
say, all-bits-one) can be perfectly conforming.
> > > I'm not sure I can get behind that. If nothing else, the compiler
> > > (or linker or loader, whatever) should disallow storing at memory
> > > location 0.
> >
> > Why should it?
>
> Because it is the law. Why can't you travel at the speed of light?
There is no such law.
[...]
> And my point is that the one, true null pointer, regardless of
> hardware is location 0:0 in memory on whatever architechure you
> use. The NULL macro may be implementation dependant, but C
> _guarantees_ that if you point a pointer at location 0:0, you are
> pointing at an invalid location, and no reading or writing is
> allowed. It is the "Ultimate Null". Praise Zero!
No, it isn't. The only basis for this is a single ambiguous statement
in K&R2. Appendix A of K&R2 and the ISO standard (both C90 and C99)
are perfectly clear on this point; there is nothing special about an
all-bits-zero pointer.
> > Here's something that might clarify things a bit (or not).
> Not.
Ok, try section 5 of the C FAQ.
> It's not K&R's finest moment. Here's a bit more context:
>
> If not, alloc must return some signal that no space is left. C
> guarantees that zero is never a valid address for data, so a return
> value of zero can be used to signal an abnormal event, in this case,
> no space.
>
> From the context it's clear that in this instance they're referring to
> a pointer value - what's returned by their alloc() function. However,
> the text fails to make clear that this does not apply to the actual
> internal representation of an address. The use of "address" here is
> infelicitous - it's either wrong or misleading. IMO this should be
> added to the errata list.
That may be so but let us not be hasty.
Here are some passages from C99.
6.3.2.3 Pointers
3 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.
4 Conversion of a null pointer to another pointer type yields
a null pointer of that type. Any two null pointers shall
compare equal.
5 An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined,
might not be correctly aligned, might not point to an entity
of the referenced type, and might be a trap representation.
6 Any pointer type may be converted to an integer type. Except
as previously specified, the result is implementation-defined.
If the result cannot be represented in the integer type, the
behavior is undefined. The result need not be in the range of
values of any integer type.
> In article <8c7d4a6e.04080...@posting.google.com>,
> junky_...@yahoo.co.in (junky_fellow) wrote:
>
> > 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?
> If you write
>
> int i = 0;
> char* q = (char *) i;
>
> then the C99 Standard guarantees that q is a null pointer.
Oh? C&V, please. AFAICT it guarantees nothing of the sort; in fact, it
suggests (albeit in a footnote) that q _should_ have the value
0x00000000 if possible, and on junky_fellow's hypothetical platform that
would definitely not be a null pointer.
OTOH, if you did this
char *q=0;
or even, more superfluously,
char *q=(char *)0;
then q would be a null pointer, since 0 is a null pointer constant, and
both assignment to and casting to a pointer object are pointer contexts.
Richard
> "Keith Thompson" <ks...@mib.org> wrote in message
> news:lnzn5ae...@nuthaus.mib.org...
> > "Mabden" <mabden@sbc_global.net> writes:
> > > So, you are saying that (on some mythical machine) I could have an
> > > array a[] that lives at location 0000:0000 of memory and point to it
> > > with ptr = &a and ptr would not be a NULL pointer?
The very fact that you have an array at that location means that it
cannot possibly be a null pointer; the null pointer is guaranteed not
ever to point at any object.
> > Yes (but please use the phrase "null pointer", not "NULL pointer";
> > NULL is a macro). I'm assuming that your 0000:0000 notation refers to
> > an all-bits-zero representation.
>
> That is what I mean, yes, as it was a popular notion in Windows programming
> denoting segment:offset. I will use "null" to mean location 0 in memory
> (0000:0000, or 0:0 for short), as in the very first addressable location
> possible on the machine.
Then you still do not get it. Null pointers _need not_ point to the
lowest existing location in memory.
> NULL is a macro, I agree, for basically (char *)0.
No, it isn't.
> This would be a zero somewhere in memory
No, it isn't.
> that the program stores upon startup and compares
> various pointers to, so if NULL happens to point to 1234:4321, and I set
> "ptr1 = ptr2 = NULL" then both pointers would point to 1234:4321.
Almost. But not quite.
> I think these things are distinct cases. My point was that null, ie: 0:0,
From this point on, your point is invalid, since null _need not_ be 0:0.
> is considered an invalid location for data. Furthermore, I believe it is
> "guaranteed" to be invalid for data in C.
Your beliefs are immaterial; only the Standard counts.
> When I state that belief, I sometimes get told I am wrong. I only have the K&R to go on. I do not own
> any reference to the "Standard this that or the other". But, didn't the K&R
> come first?
So bloody what? Anglo-Saxon came before English, but when you check your
spelling, do you use the OED, or the DOE?
> To make a religious reference,
Please don't. It only makes you sound like a prat.
> "We have a new way of doing it now!" "You aren't up to the new standard..."
> But I sit back and look at MY gospel, and say, "Know, you are wrong! And
> your standard is wrong if you are telling me the truth about what it says."
Then, to put it bluntly, you are an idiot, and you'll never program in
C. In the light of this, all the rest of your post is unimportant.
Basically, you cannot be taught; you cannot be reasoned with; you are
not worth our attention. Welcome to the killfile.
Richard
Um, no. The standard guarantees that a null pointer constant,
converted to a pointer type, results in a null pointer, but i is not a
null pointer constant. The value of q will be the
implementation-defined result of converting the int value 0 to char*;
this is typically all-bits-zero even if a null pointer is 0x12345678.
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.
> Christian Bau <christ...@cbau.freeserve.co.uk> wrote:
>
> > In article <8c7d4a6e.04080...@posting.google.com>,
> > junky_...@yahoo.co.in (junky_fellow) wrote:
> >
> > > 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?
>
> > If you write
> >
> > int i = 0;
> > char* q = (char *) i;
> >
> > then the C99 Standard guarantees that q is a null pointer.
>
> Oh? C&V, please. AFAICT it guarantees nothing of the sort; in fact, it
> suggests (albeit in a footnote) that q _should_ have the value
> 0x00000000 if possible, and on junky_fellow's hypothetical platform that
> would definitely not be a null pointer.
1. Converting a null pointer constant to a pointer type yields a null
pointer. (BTW in an assignment char* q = 0; there is an actual
conversion from int to char*; this rule guarantees that the result is a
null pointer).
2. The result of conversion from integer to pointer type is
implementation defined, in other words, the result is defined.
3. The result of converting an integer value of zero is defined because
of (2), so far we know nothing about the result, but it will always be
the same because it is defined. In the special case that the integer
value of zero happens to be a constant integer expression, (1)
guarantees that the result is a null pointer. Since the result is always
the same, and sometimes a null pointer, it is always a null pointer.
> Christian Bau <christ...@cbau.freeserve.co.uk> writes:
> [...]
> > If you write
> >
> > int i = 0;
> > char* q = (char *) i;
> >
> > then the C99 Standard guarantees that q is a null pointer. On this
> > implementation it means q will point to address 0x12345678 and it will
> > not be equal to p. Unlike most current compilers, a compiler for this
> > implementation will have to produce real code to cast from int to char*.
>
> Um, no. The standard guarantees that a null pointer constant,
> converted to a pointer type, results in a null pointer, but i is not a
> null pointer constant. The value of q will be the
> implementation-defined result of converting the int value 0 to char*;
> this is typically all-bits-zero even if a null pointer is 0x12345678.
The implementation-defined result of the conversion must be a null
pointer if the int value 0 happens to be a null pointer constant. In
other words, the implementation is not free to define conversion from
int to char* in completely arbitrary ways.
In some cases, a value of zero must be converted to a null pointer. But
a conversion just converts values, it doesn't know about any syntactical
details how the value was derived; to the conversion a zero that happens
to be a null pointer constant and a zero that happens to be the value of
an int variable are the same. The result cannot be sometimes a null
pointer and sometimes not a null pointer. So in both cases the
conversion must give the same result, which must be a null pointer.
> > Um, no. The standard guarantees that a null pointer constant,
> > converted to a pointer type, results in a null pointer,
> > but i is not a null pointer constant.
> The implementation-defined result of the conversion must be a null
> pointer if the int value 0 happens to be a null pointer constant.
No.
The ordinary rules of conversion don't apply to
char *q = 0;
The assignment of a null pointer constant,
to a pointer object, is a special case.
int i = 0;
char* q = (char *)i;
is just implementation defined, and that's all that there is to it.
--
pete
> In article <4111e372....@news.individual.net>,
> r...@hoekstra-uitgeverij.nl (Richard Bos) wrote:
>
> > Christian Bau <christ...@cbau.freeserve.co.uk> wrote:
> >
> > > In article <8c7d4a6e.04080...@posting.google.com>,
> > > junky_...@yahoo.co.in (junky_fellow) wrote:
> > >
> > > > 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?
> >
> > > If you write
> > >
> > > int i = 0;
> > > char* q = (char *) i;
> > >
> > > then the C99 Standard guarantees that q is a null pointer.
> >
> > Oh? C&V, please. AFAICT it guarantees nothing of the sort; in fact, it
> > suggests (albeit in a footnote) that q _should_ have the value
> > 0x00000000 if possible, and on junky_fellow's hypothetical platform that
> > would definitely not be a null pointer.
>
> 1. Converting a null pointer constant to a pointer type yields a null
> pointer.
Irrelevant, since there are two conversions in that snippet: one in
which an integral constant zero is converted to an int value, and one in
which an int value is converted to a pointer value. Neither of these
involve a null pointer constant in a pointer context.
> 2. The result of conversion from integer to pointer type is
> implementation defined, in other words, the result is defined.
Yes, but not necessarily a null pointer.
> 3. The result of converting an integer value of zero is defined because
> of (2), so far we know nothing about the result, but it will always be
> the same because it is defined.
Not necessarily. It may be defined as "the current user segment, with
the integer value as the offset" - with the current user segment
changing from program run to program run.
> In the special case that the integer
> value of zero happens to be a constant integer expression,
That makes about as much sense as "in the case that the person you're
talking to is a photograph of your brother". A constant integer
expression is a compile-time feature. An object with a value is a
run-time feature. The latter can never be the former.
Again: the exception is for compile-time, literal constant expressions
_alone_. Not for run-time values.
Richard
thanx...
> Fools are always brave; it goes with the territory. And Brian assures me I
> am a fool (thanks for that Brian, I think the world of your people skills
> and I'm sure you have many loving friends).
Please quote some post where I called you a fool. I don't believe I did
anything of sort, or even came close to it.
Brian Rodenborn
Nor was I, when I composed that message.
> Here are some passages from C99.
Indeed they are, and they agree with me. If you feel they do not,
perhaps you should have explained why, rather than merely quoting
them without comment.
--
Michael Wojcik michael...@microfocus.com
Shakespeare writes bombast and knows it; Mr Thomas writes bombast and
doesn't. That is the difference. -- Geoffrey Johnson
>And my point is that the one, true null pointer, regardless of hardware is
>location 0:0 in memory on whatever architechure you use.
The idea that addresses consist of a segment and offset is just a
feature of some architectures. Even on the most common architecture
that uses that feature - the x86 - most current operating systems
provide a linear address space in which segments are irrelevant to
almost all programmers.
-- Richard
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.
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.
And assuming a prat is a bad thing to be, I'll have to say you seem like as
well, for your constantly turning the argument off-course with all the
harping on the null pointer issue which we all agree on, even me.
--
Mabden
No kidding. It is just a way of expressing location zero in memory, as I
explained in the bit you snipped. I am not talking about any particular
architecture. I am talking about any machine that runs a C program.
--
Mabden
>No kidding. It is just a way of expressing location zero in memory, as I
>explained in the bit you snipped.
In a segmented architecture, "location zero" may not mean anything at
all. In a non-segmented architecture, "0:0" is meaningless. You're
just used to x86s and think it's a natural notation, when in fact it's
completely architecture-specific.
-- Richard
> 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.
>
> 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.
There is nothing special about location 0, or location 1, or location 2,
or location 3 and so on and so on.
In many C implementations, any hardware pointer that the implementation
could use must point _somewhere_, so the location that a null pointer
points to would be special in that it cannot be used for holding C
objects. But for example on an 80286 implementation using segmented
pointers, the null pointer would most likely be represented by a segment
of 0 and an offset of 0, and on that hardware this combination doesn't
point _anywhere_. Not only does a null pointer not point to any C
object, it doesn't point anywhere at all.
<snip>
> p ^= p; /* illegal */
<snip>
>Here's a cleaner way to do what you're trying to do:
> memset(&ptr, 0, sizeof(ptr));
*smack on the forehead*
Yeah, that's what I meant. I know the xor operation is illegal on
pointers, but I couldn't think of memset. Let's see now, 999 more
smacks on the forehead before I can explain hypothetical situations
with legal code.
--
aib
ISP e-mail accounts are good for receiving spam.
As you know, malloc() will return a pointer with all bits zero if the
allocation fails and that happens to be the representation of a null
pointer.
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.)
In any case, 99+% of the time there's no need to care about whether a
particular address is all-bits-zero or not -- and if you do care, then
you're doing some very system-specific stuff and you'd better know
exactly what you're doing.
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.)
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 ?
> "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
> 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.
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
> 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-newsgroup/comp/comp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html
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.
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
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" <ks...@mib.org> wrote in message
news:ln7jsct...@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
> 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.]
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 michael...@microfocus.com
Is it any wonder the world's gone insane, with information come to be
the only real medium of exchange? -- Thomas Pynchon
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
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:cf0ai...@news3.newsguy.com>
Michael Wojcik <mwo...@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.
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:ln7jsct...@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?
> Christian Bau <christ...@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.
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
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.
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.)
Christian Bau wrote:
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"
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.
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.
<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
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.
>
--
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
> 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.
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 michael...@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)
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-)}
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:joeww...@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
> In article <lnfz6z6...@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.
> 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
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).
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 michael...@microfocus.com
Do not "test" parts, as this may compromise sensitive joinery. Those who
suffer difficulty should abandon the enterprise immediately. -- Chris Ware
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 michael...@microfocus.com
Recently, they appeared at the reopening of the Brookdale Library,
luring passersby with the opportunity to be anonymously silly.
> 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"
>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
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
> In article <ln3c30t...@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
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.
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.
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 michael...@microfocus.com
Push up the bottom with your finger, it will puffy and makes stand up.
-- instructions for "swan" from an origami kit
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.
>
> "Michael Wojcik" <mwo...@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.