Unix Programming - The difference between 0 and NULL?

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > June 2005 > The difference between 0 and NULL?





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author The difference between 0 and NULL?
umagnum338@netscape.net

2005-06-22, 8:49 pm

Hi,

>From the subject you're probably thinking I'm an idiot but I've

encountered something that I'm hoping those more experienced than I can
answer. At work, I was working my way through a serial testing program
that was written a while back and wouldn't build without some help.

While trouble shooting I noticed that the program was bailing right
from the beginning because main() looked like this:

/* include */

int main( int argc, char *argv[] ) {
ModemObject M;

if( argc == 1 ) {
printf( "You must specify a file; e.g. /dev/ttyS0\n" );
return 1;
}
// continue
return 0;
}

Well, the program (when called with no arguments) wasn't printing the
string if argc is 1, so I made the obvious conclusion and began to
track down what was happening in ModemObject. Now, this is a C++
program (the calls to printf() notwithstanding) and ModemObject is a
class. I noticed there existed only one ctor for the class and it was
simple enough. It's a no argument ctor that initializes 3 variables in
the class, 2 ints and a pointer. I noticed that the pointer was being
initialized to 0. I changed this to NULL and recompiled and walla, the
program worked.

Now, I'm befuddled. I thought NULL was 0! What gives? As I see it,
there are two possibilities. First, either there is some difference
between 0 and NULL because of how NULL is defined, or something else
took place in the build environment (which is far too complex for such
a simple application). The build env starts with a Makefile that
recursively calls Makefiles in about 12 subdirectories going about 3
subdirectories deep. As I mentioned, either NULL is slightly different
than 0 (because of definition) or in modifying these source code files
I changed something that was lacking in previous builds.

It is significant to note that the only copy I could tar up of this
program was already built, but not functioning in more recent versions
of Linux. I couldn't find a source tree that didn't have complied code
in it.

Suggestions?

Thanks,
Andy

David Schwartz

2005-06-22, 8:49 pm


<umagnum338@netscape.net> wrote in message
news:1119487393.942155.186750@g14g2000cwa.googlegroups.com...

> Well, the program (when called with no arguments) wasn't printing the
> string if argc is 1, so I made the obvious conclusion and began to
> track down what was happening in ModemObject. Now, this is a C++
> program (the calls to printf() notwithstanding) and ModemObject is a
> class. I noticed there existed only one ctor for the class and it was
> simple enough. It's a no argument ctor that initializes 3 variables in
> the class, 2 ints and a pointer. I noticed that the pointer was being
> initialized to 0. I changed this to NULL and recompiled and walla, the
> program worked.


This change likely had no effect. Perhaps your first compile was bad
somehow, due to using mismatched header files or some similar problem.

DS


Pascal Bourguignon

2005-06-23, 2:48 am

"David Schwartz" <davids@webmaster.com> writes:

> <umagnum338@netscape.net> wrote in message
> news:1119487393.942155.186750@g14g2000cwa.googlegroups.com...
>
>
> This change likely had no effect. Perhaps your first compile was bad
> somehow, due to using mismatched header files or some similar problem.


Indeed, even if (void*)0 has a different bit pattern than 0, C, and
even more so C++, define void* p=0; as setting p to (void*)0,
(and p==0 as p==(void*)0).

Either you have a bug in the compiler (try to revert to pointer=0), or
another gremling.

--
__Pascal Bourguignon__ http://www.informatimago.com/
The mighty hunter
Returns with gifts of plump birds,
Your foot just squashed one.
Floyd L. Davidson

2005-06-23, 2:48 am

umagnum338@netscape.net wrote:
>Hi,
>
>From the subject you're probably thinking I'm an idiot but I've


On the contrary, it happens to be a rather complex and not easy
to initially comprehend bit of language definition. Almost
everyone at some point has to ask the same question!

>the class, 2 ints and a pointer. I noticed that the pointer was being
>initialized to 0. I changed this to NULL and recompiled and walla, the
>program worked.


As others have pointed out, that is very unlikely. There *has*
to have been something else to it.

>Now, I'm befuddled. I thought NULL was 0! What gives? As I see it,


Regardless, nobody else has gone into detail about your question
of just what is NULL, so I'm going to. Except, I'm going to
explain what it is in the C language, not C++. Perhaps someone
else can point out where they differ.

There are three distinct entities to be aware of:

1) the /NULL/ macro
2) a /null/ /pointer/ /constant/
3) a /null/ /pointer/

/NULL/ is a macro, defined in a header file, and is guaranteed
to expand in the pre-processor stage to a /null/ /pointer/
/constant/. It is purely a source code device, meant to make
source code easier for humans to read. It indicates an invalid
address which cannot point to any valid object and will
guaranteed compare equal to zero. Note that the C compiler
itself *never* sees the NULL, only a /null/ /pointer/ /constant/.

A /null/ /pointer/ /constant/ is defined as either an "An
integer constant expression with the value 0, or such an
expression cast to type void *". This is a source code device.
Note that it does not have any particular bit pattern
representation, because it exist *only* in the source code.

The compiler converts a /null/ /pointer/ /constant/ in the
source code to a /null/ /pointer/ value in the output. The
/null/ /pointer/ bit pattern is implementation specific. It is
whatever the compiler implementor decided to make it. Note that
*each* *type* (char, int, long, etc) has it's own /null/
/pointer/ bit pattern, and they are not necessarily the same!
(However, the bit pattern commonly is all bits 0 just to make it
easy for the compiler implementor. :-)

The compiler must guarantee that a /null/ /pointer/ will not
equate true when compared to any valid object or function. It
must also guarantee that comparing any two /null/ /pointers/ or
any /null/ /pointer/ and a /null/ /pointer/ /constant/ will
equate true. That can be done by any type of internal magic the
implementor wishes to use, and does not mean the actual bit
patterns are the same.

Here is most of the pertinent part of the C99 Standard,

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/.55) 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.

Footnote 55 says,

55) The macro NULL is defined in <stddef.h> (and other
headers) as a null pointer constant; see 7.17.


That's a good bit of information to sort out. A couple of
things that may not be obvious at first... NULL should *only*
be used in a pointer context. "int x = NULL;" is poor style,
even if it works.

Another, is this:

int *p = NULL; /* p now has a null pointer value */
int *p = 0; /* p now has a null pointer value */

int x = 0;
p = x; /* p now has a "valid address" equal to 0 */

That is because NULL in converted to a /null/ /pointer/
/constant/ and 0 already is a /null/ /pointer/ /constant/.

But x set equal to 0, is just 0.

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Ari Lukumies

2005-06-23, 7:51 am

umagnum338@netscape.net wrote:
> While trouble shooting I noticed that the program was bailing right
> from the beginning because main() looked like this:
>
> /* include */
>
> int main( int argc, char *argv[] ) {
> ModemObject M;
>
> if( argc == 1 ) {
> printf( "You must specify a file; e.g. /dev/ttyS0\n" );
> return 1;
> }
> // continue
> return 0;
> }
>
> Well, the program (when called with no arguments) wasn't printing the
> string if argc is 1,


(which happens only if the program is run without any arguments)

> so I made the obvious conclusion and began to
> track down what was happening in ModemObject. Now, this is a C++
> program (the calls to printf() notwithstanding) and ModemObject is a
> class. I noticed there existed only one ctor for the class and it was
> simple enough. It's a no argument ctor that initializes 3 variables in
> the class, 2 ints and a pointer. I noticed that the pointer was being
> initialized to 0. I changed this to NULL and recompiled and walla, the
> program worked.


Some of the includes redefined NULL?

void *p = NULL;
void *p = 0;

should yield the same (since, by definition, NULL is defined as
(void*)0) - although the latter is recommended in C++ circles.

A possibility also is, that the pointer you refer to, is of some class
also, and the assignment (or constructor assignment) is redefined to
something else with it.

Can you show us the class definition of ModemObject and its
constructor? We'd be much wiser then.

-atl-
--
A multiverse is figments of its own creations
Chris Friesen

2005-06-23, 6:00 pm

Floyd L. Davidson wrote:

> The compiler must guarantee that a /null/ /pointer/ will not
> equate true when compared to any valid object or function. It
> must also guarantee that comparing any two /null/ /pointers/ or
> any /null/ /pointer/ and a /null/ /pointer/ /constant/ will
> equate true. That can be done by any type of internal magic the
> implementor wishes to use, and does not mean the actual bit
> patterns are the same.


Of course this is all complicated by the fact that on many platforms it
is actually possible to request that memory be mapped at address 0. If
you do so, then it is possible to dereference a NULL pointer and
actually get valid data.

The reason for this is that some systems have hardware that is mapped at
very low addresses, so while the system will not give you a page at
address zero on its own, it will give you one if you ask for it.

Chris
Chris Friesen

2005-06-23, 6:00 pm

Floyd L. Davidson wrote:

> Another, is this:
>
> int *p = NULL; /* p now has a null pointer value */
> int *p = 0; /* p now has a null pointer value */
>
> int x = 0;
> p = x; /* p now has a "valid address" equal to 0 */


Of course you'd need "p = (int*) x;" in practice.

Also, many compilers will generate the same code for all three cases,
based on the knowledge that the system will not by default map memory at
address zero.

This may not be strictly correct behaviour, but it is common.

Chris
Erik Max Francis

2005-06-23, 6:00 pm

Chris Friesen wrote:

> Of course this is all complicated by the fact that on many platforms it
> is actually possible to request that memory be mapped at address 0. If
> you do so, then it is possible to dereference a NULL pointer and
> actually get valid data.


As pointed out in the post you were replying to, there's not even a
guarantee that a null pointer corresponds to an address of all-bits zero
(if that is even legal on the architecture in question), so this is
something of a red herring.

Yes, though, it is possible that the address pointed to by the null
pointer may in fact be allowed to contain valid data. In other words,
it's not guaranteed that dereferencing a null pointer will result in a
trap or segmentation fault or any other diagnostic. But that's because
it's undefined behavior, not because a diagnostic should be expected.

--
Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
Conversation is the enemy of good wine and food.
-- Alfred Hitchcock
Gordon Burditt

2005-06-23, 6:00 pm

>Of course this is all complicated by the fact that on many platforms it
>is actually possible to request that memory be mapped at address 0. If
>you do so, then it is possible to dereference a NULL pointer and
>actually get valid data.
>
>The reason for this is that some systems have hardware that is mapped at
>very low addresses, so while the system will not give you a page at
>address zero on its own, it will give you one if you ask for it.


If you're trying to imply here that there are NO systems that will
give you address 0 mapped without asking specially for it, that's
not correct (PDP-11 running UNIX v6 I believe is an example).

There are systems which will give you address 0 mapped, and you may
not ask for anything else, because there is no way to do so. (Tandy
6000 running Xenix is one example (it had very crude memory
management hardware, 2 base-limit registers, one hardwired to start
at virtual address 0) and I suspect the PDP-11 running UNIX v6 is
another).

Gordon L. Burditt
Nils Weller

2005-06-23, 6:00 pm

In article <11blmmbgdkudha0@corp.supernews.com>, Gordon Burditt wrote:
> [...]
> If you're trying to imply here that there are NO systems that will
> give you address 0 mapped without asking specially for it, that's
> not correct (PDP-11 running UNIX v6 I believe is an example).


Two more relevant examples are HP-UX and AIX. Page zero on these systems
is usually mapped read-only. On HP-UX, the way you invoke the linker
determines whether it is or isn't mapped; HP's compiler invokes it such
that it is mapped, gcc does not. The chatr program can be used to change
this setting as well. I know of no way to turn this off on AIX, but
there may well be one.

--
Nils R. Weller, Bremen / Germany
My real email address is ``nils<at>gnulinux<dot>nl''
.... but I'm not speaking for the Software Libre Foundation!
Chris Friesen

2005-06-23, 6:00 pm

Gordon Burditt wrote:

> If you're trying to imply here that there are NO systems that will
> give you address 0 mapped without asking specially for it, that's
> not correct (PDP-11 running UNIX v6 I believe is an example).


I'm actually not trying to imply that, for the reason you give. On the
PDP is a "NULL" pointer equal to an all-zeros address? I know some
systems use some other bit pattern for invalid pointers.

I'm saying that there are fairly common systems on which a "NULL"
pointer is equal to an all-zeros address, but dereferencing a "NULL"
pointer may work, and where you can store objects at the address
corresponding to a "NULL" pointer.

By default the system will not give you this behaviour, but if you
specifically ask for it, it will let you.

> There are systems which will give you address 0 mapped, and you may
> not ask for anything else, because there is no way to do so. (Tandy
> 6000 running Xenix is one example (it had very crude memory
> management hardware, 2 base-limit registers, one hardwired to start
> at virtual address 0) and I suspect the PDP-11 running UNIX v6 is
> another).


Interesting.

Chris
Gordon Burditt

2005-06-23, 6:00 pm

>> If you're trying to imply here that there are NO systems that will
>
>I'm actually not trying to imply that, for the reason you give. On the
>PDP is a "NULL" pointer equal to an all-zeros address? I know some


Yes. If the PDP-11 had used 0xDEAD for a NULL pointer, we'd probably
have lots of people swearing up and down that ALL systems do it that way,
since it is the system C originated on.

>systems use some other bit pattern for invalid pointers.


>I'm saying that there are fairly common systems on which a "NULL"
>pointer is equal to an all-zeros address, but dereferencing a "NULL"
>pointer may work, and where you can store objects at the address
>corresponding to a "NULL" pointer.


Fine.

>By default the system will not give you this behaviour, but if you
>specifically ask for it, it will let you.


The above paragraph is *WRONG*, there are systems where the system
*WILL* give you that behavior *BY DEFAULT*, and there are furthermore
systems that will give you that behavior *AND YOU CANNOT CHANGE IT
AT ALL*. Yes, most if not all of these systems use all-bits-zero
as a NULL pointer.
[vbcol=seagreen]

Also consider systems where there is no hardware memory mapping at
all, and RAM starts at 0.

Gordon L. Burditt
Chris Friesen

2005-06-23, 6:00 pm

Gordon Burditt wrote:

[vbcol=seagreen]
> Fine.


[vbcol=seagreen]
> The above paragraph is *WRONG*, there are systems where the system
> *WILL* give you that behavior *BY DEFAULT*, and there are furthermore
> systems that will give you that behavior *AND YOU CANNOT CHANGE IT
> AT ALL*. Yes, most if not all of these systems use all-bits-zero
> as a NULL pointer.


Hold on a sec, I think you've misunderstood what I'm trying to say.

In the above statement that I made "the system" refers only to the
systems which I was discussing in my earlier paragraph above, not all
systems that are out there.

One such example is my ppc machine. My point is that by default,
dereferencing NULL pointers on that machine will cause a segfault, but
that there are ways around it.

I brought this whole thing up as a exception to the NULL pointer values
not being a valid address.

You've now brought up machines where dereferencing a NULL pointer
doesn't even cause a segfault by default, which makes them even more of
an exception to the standard C behaviour.

I really don't think we disagree on the fundamentals.

Chris
Floyd L. Davidson

2005-06-23, 6:00 pm

Chris Friesen <cfriesen@nortel.com> wrote:
>Floyd L. Davidson wrote:
>
>
>Of course this is all complicated by the fact that on many
>platforms it is actually possible to request that memory be
>mapped at address 0. If you do so, then it is possible to
>dereference a NULL pointer and actually get valid data.


Dereferencing a /null pointer/ is undefined behavior. You might
get what appears to be valid data, but by definition the entire
program is invalid after you've done that.

>The reason for this is that some systems have hardware that is
>mapped at very low addresses, so while the system will not give
>you a page at address zero on its own, it will give you one if
>you ask for it.


But you are not allowed to access if by dereferencing a /null/
/pointer/.

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Floyd L. Davidson

2005-06-23, 6:00 pm

gordonb.kgdff@burditt.org (Gordon Burditt) wrote:
>There are systems which will give you address 0 mapped, and you may
>not ask for anything else, because there is no way to do so. (Tandy
>6000 running Xenix is one example (it had very crude memory
>management hardware, 2 base-limit registers, one hardwired to start
>at virtual address 0) and I suspect the PDP-11 running UNIX v6 is
>another).


Is there an ISO/ANSI Standard C compiler available for those
platforms?

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Floyd L. Davidson

2005-06-23, 6:00 pm

Chris Friesen <cfriesen@nortel.com> wrote:

>I brought this whole thing up as a exception to the NULL pointer
>values not being a valid address.


There are no exceptions. But... that is the ISO/ANSI C Standard,
and *does* *not* *apply* to the UNIX v6 compiler, for example.

>You've now brought up machines where dereferencing a NULL
>pointer doesn't even cause a segfault by default, which makes
>them even more of an exception to the standard C behaviour.


--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Floyd L. Davidson

2005-06-23, 6:00 pm

Chris Friesen <cfriesen@nortel.com> wrote:
>Floyd L. Davidson wrote:
>
>
>Of course you'd need "p = (int*) x;" in practice.


That is not a list of all ways to assign a 0 bit pattern to a
pointer variable. It is merely a demonstration that it makes a
difference *what* is assigned to the pointer, and an all bits
are 0 pattern is *not* the difference. Using a /null/ /pointer/
/constant/ is the significance. There are dozens of other ways
to demonstrate that point, but the above 4 lines seemed to me to
be the clearest way to make the point.

>Also, many compilers will generate the same code for all three
>cases, based on the knowledge that the system will not by
>default map memory at address zero.
>
>This may not be strictly correct behaviour, but it is common.


Why is that not strictly correct? The standard describes what
must happen when a /null/ /pointer/ /constant/ is assigned, and
if that happens, all is well. It does *not* say that the other
construct cannot also have the same side effects.

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
David Schwartz

2005-06-23, 6:00 pm


"Chris Friesen" <cfriesen@nortel.com> wrote in message
news:11bm9u56v2vp431@corp.supernews.com...

> I brought this whole thing up as a exception to the NULL pointer values
> not being a valid address.


The NULL pointer value is never a valid address. For example, the return
value of 'malloc' or 'new' cannot test equal to NULL.

> You've now brought up machines where dereferencing a NULL pointer doesn't
> even cause a segfault by default, which makes them even more of an
> exception to the standard C behaviour.


That's not an exception. The C standard does not say what happens when
you derefence a NULL pointer because that is not legal. Anything can happen,
and the standard is satisfied.

DS


Gordon Burditt

2005-06-23, 6:00 pm

>I brought this whole thing up as a exception to the NULL pointer values
>not being a valid address.


They aren't a valid address because ISO C says they aren't a valid
address, regardless of whether they actually work or not.
"undefined behavior" allows *ANYTHING* to happen.

>You've now brought up machines where dereferencing a NULL pointer
>doesn't even cause a segfault by default, which makes them even more of
>an exception to the standard C behaviour.


In the above paragraph, what do you mean by the phrase "standard C
behaviour"?

ANSI/ISO C does not require a segfault for any reason whatever, and
permitting writes to the memory "pointed at" by a null pointer is
just as much in the spirit of the C standard as causing a segfault
or causing George W. Bush to fly out of an actual demon's nose.
If you are referring to the C standard, you're wrong here.

Letting you write on memory by dereferencing a null pointer is
common (and default) behavior on some:
(a) historical machines which C originated on (the PDP-11)
(b) machines with no memory management hardware, even current ones,
(embedded systems),
(c) machines with simple memory management hardware not flexible
enough to map out address 0 (Tandy 6000 and Intel *86
machines being used in real mode (ok, maybe the Intel *86
used in real mode belongs in (b) above), and
(d) machines with complex memory management hardware where
defaulting to compatability mode was considered more
important than trapping errors (seems to me this
applied to 4.1 BSD on a Vax) even though trapping
the error was possible and an available option.

and if you're trying to make a case for segfaulting being the
"standard historical behavior", I think the opposite: allowing such
a write is the "standard historical behavior".

If you mean that segfaulting on write by dereferencing NULL is
standard practice on machines with complex, current non-embedded
CPUs for desktop computers and current OSs, I'll concede that, but
it's a real stretch to consider that the meaning of the phrase
"standard C behaviour".

>I really don't think we disagree on the fundamentals.


But I think we have a lot of disagreement over terminology.

Gordon L. Burditt
Nils Weller

2005-06-23, 6:00 pm

In article <8764w5r0n3.fld@barrow.com>, Floyd L. Davidson wrote:
> umagnum338@netscape.net wrote:
> [...]
>
> Regardless, nobody else has gone into detail about your question
> of just what is NULL, so I'm going to. Except, I'm going to
> explain what it is in the C language, not C++. Perhaps someone
> else can point out where they differ.
> [...]


It may be interesting to note that NULL is a place where C is more type-
safe than C++; Since C++ does not implicitly convert void pointer
expressions to non-void pointer expressions, NULL has to be an ``integer
constant expression'' in C++, while it can be, and frequently is defined
as, ``such an expression cast to type void *'' in C. In other words, the
C++ definition of NULL usually looks like this:

#define NULL 0

.... whereas the C definition usually looks like this:

#define NULL ((void *)0)

This means that, given such a definition, any use of NULL in a context
where a pointer expression is not permitted will yield a compiler
diagnostic in C, but not in C++.

Another interesting implication that comes to mind is the fact that
the C++ version is more likely to break code that passes an uncast NULL
to a variadic function;

(void) execl(prog, arg1, arg2, ..., NULL); /* should be (char *)NULL! */

This code is invalid because execl() expects a list of ``char *''
arguments, but since it is a variadic function, the compiler cannot
know the expected argument type a priori and has to trust that you
always pass arguments of the right type. Now, if NULL is defined as a
void pointer expression, the code will work correctly. But if it is
defined as 0 and the size of an ``int'' differs from that of a
``char *'', and/or these types are simply passed passed to the function
in different ways, or some other such problem occurs, the code is more
likely to break - thus making the bug visible.

Both definitions have advantages and disadvantages.

--
Nils R. Weller, Bremen / Germany
My real email address is ``nils<at>gnulinux<dot>nl''
.... but I'm not speaking for the Software Libre Foundation!
Chris Friesen

2005-06-23, 6:00 pm

Floyd L. Davidson wrote:
> Chris Friesen <cfriesen@nortel.com> wrote:


[vbcol=seagreen]
[vbcol=seagreen]
[vbcol=seagreen]
> Why is that not strictly correct? The standard describes what
> must happen when a /null/ /pointer/ /constant/ is assigned, and
> if that happens, all is well. It does *not* say that the other
> construct cannot also have the same side effects.


I was suggesting that it would not be strictly correct because the third
case is a valid address, while the other two are null pointers.

Consider the following thought experiment for machines where the NULL
pointer value is all zeros.

I have some valid object.
I cause the system to map memory at the zero address.
I create a pointer with the address of zero.
I copy my valid object to the pointer with the zero address.

If I then compare a NULL pointer with the pointer to this object, from
what you've said the result of that comparison should be false.

I suspect that the result will be true on many systems.

Note that I am not saying that this is correct, only that I suspect many
systems are not strictly adhering to the rules.

Chris
Gordon Burditt

2005-06-23, 8:48 pm

>Consider the following thought experiment for machines where the NULL
>pointer value is all zeros.
>
>I have some valid object.
>I cause the system to map memory at the zero address.


This leads to, at best, implementation-defined behavior, unless
it's done for you already and it's a null step.

>I create a pointer with the address of zero.
>I copy my valid object to the pointer with the zero address.


Once you do this, you've broken the rulebook. WHATEVER happens is
correct behavior. This isn't like etiquette, where there is at
most one correct fork to use for any occasion.

>If I then compare a NULL pointer with the pointer to this object, from
>what you've said the result of that comparison should be false.


No, whatever happens is not wrong. The result of the comparison
need not even be (stopping time in the universe is one possibility).

>I suspect that the result will be true on many systems.


No matter what happens, the result is not wrong.

>Note that I am not saying that this is correct, only that I suspect many
>systems are not strictly adhering to the rules.


Once you've invoked undefined behavior, there *ARE* no rules.

Gordon L. Burditt
Gordon Burditt

2005-06-23, 8:48 pm

>>There are systems which will give you address 0 mapped, and you may
>
>Is there an ISO/ANSI Standard C compiler available for those
>platforms?


At one point I had a 1990-or-so version of (68000) gcc ported to
the Tandy 6000, to the point that it would compile itself and a lot
of other stuff. Does that count? Granted, that's not the current
standard. And the library probably needed quite a bit of work.

As to the PDP-11, wasn't there a PDP-11 cross-compile mode in the
4.3BSD Vax distribution? How close to the standard (C90) was that
(even though the standard wasn't out yet by the time the compiler
was released)?

Gordon L. Burditt
Chris Friesen

2005-06-23, 8:48 pm

Gordon Burditt wrote:

[vbcol=seagreen]
> Once you do this, you've broken the rulebook. WHATEVER happens is
> correct behavior. This isn't like etiquette, where there is at
> most one correct fork to use for any occasion.


That makes sense to me.

In an earlier post Floyd claimed that the sequence

int x = 0;
int *p = (int *)x;

would result in a pointer with a valid address equal to zero since it
was not syntactically assigned zero, but rather numerically assigned a zero.

It was based on the above claim that I designed my thought experiment.

Was that claim then incorrect, and it is impossible to have a valid
address that is numerically zero (for those machines which represent
NULL as an all-zeros value)?


Chris
Gordon Burditt

2005-06-23, 8:48 pm

>>>I create a pointer with the address of zero.
>
Incidentally, one of the reasons why strange things might happen is
that you've scribbled all over the code.[vbcol=seagreen]
>
>That makes sense to me.
>
>In an earlier post Floyd claimed that the sequence
>
>int x = 0;
>int *p = (int *)x;
>
>would result in a pointer with a valid address equal to zero since it
>was not syntactically assigned zero, but rather numerically assigned a zero.


I don't think the C standard defines "valid address" anywhere.

There's a real distinction here between assigning a null pointer
and assigning all-bits-zero where a null pointer is NOT all-bits-zero.
Of course, integer-to-pointer conversion might involve trig functions,
but that's unusual.

>It was based on the above claim that I designed my thought experiment.
>
>Was that claim then incorrect, and it is impossible to have a valid
>address that is numerically zero (for those machines which represent
>NULL as an all-zeros value)?


"valid address" in this context means "one which the standard guarantees
is valid". Although you may get some argument about this, I claim
the standard does not guarantee that the statement, where x is an
integer variable loaded from an integer constant in the program:
(int *) x;
will not segfault (even though it's highly likely to be optimized to nothing,
and no dereference is involved).

(For that matter, the statement:
INT_MAX+1;
might trap on overflow.)

If you take *ANY* integer constant, assign it to an int variable,
and then cast it to a pointer and dereference it, you can't be sure
it won't segfault.

There are real machines, such as Intel *86 in protected mode "large
model" (address includes the segment register) where loading an
arbitrary bit pattern into a segment register will cause a trap,
WITHOUT requiring a dereference. The all-bits-zero segment register
is a special case: you can load, but not dereference. Few if any
UNIX-like systems currently use Intel 32-bit large model (48-bit
pointers). This may change as small model ("only 4 gig") starts
cramping GUI programs, and processors with 4 gig of first-level
cache become popular.

If you cast a (32-bit) int to a (48-bit) pointer on a 32-bit
large-model Intel system, the compiler might prefix an all-bits-zero
segment register, which means that ANY int cast to a pointer is
treated as a null pointer, and dereferencing it causes a trap.

If by "valid address" you mean you can load up the pointer and access
the memory like any other address, well, you've invoked undefined
behavior, which means the program can do ANYTHING, which includes
working like you expect. And a lot of compilers just generate
code with no special code for the null pointer case. However, I'm
not willing to call that a "valid address", even though all your
experiments show it "works". Experiments can never disprove
undefined behavior.

Incidentally, on a machine where a NULL pointer is *NOT* all-bits-zero:

int x = 0;
int *i1 = 0;
int *i2 = x;

i1 may well have the value 0xdeadbeef, and i2 have the all-bits-zero
pattern. The i1 line has a null pointer constant in it. The x line
doesn't, and the i2 line doesn't.

Gordon L. Burditt
Floyd L. Davidson

2005-06-24, 2:48 am

Chris Friesen <cfriesen@nortel.com> wrote:
>Gordon Burditt wrote:
>
>
>
>That makes sense to me.
>
>In an earlier post Floyd claimed that the sequence
>
>int x = 0;
>int *p = (int *)x;
>
>would result in a pointer with a valid address equal to zero


I put "valid address" in quotes, to signify that it doesn't mean
it is actually valid, just that it appears to be.

: int x = 0;
: p = x; /* p now has a "valid address" equal to 0 */
:
:That is because NULL in converted to a /null/ /pointer/
:/constant/ and 0 already is a /null/ /pointer/ /constant/.
:
:But x set equal to 0, is just 0.

My point was that it is a pointer with all bits set to 0, and
yet is not a /null/ /pointer/.

Technically, if I've got this right, dereferencing p above would
be legal C (which will probably get a segmentation fault,
because it is an invalid address), while dereferencing p that is
assigned a /null/ /pointer/ /constant/ value would be undefined
behavior (and as noted, there is no wrong result).

>since it was not syntactically assigned zero, but rather
>numerically assigned a zero.
>
>It was based on the above claim that I designed my thought experiment.
>
>Was that claim then incorrect, and it is impossible to have a
>valid address that is numerically zero (for those machines which
>represent NULL as an all-zeros value)?


The compiler would have to handle it correctly. If it is
designed to work where a 0 bit pattern is also a valid address,
then it would have to somehow distinquish between the two.

Some platforms used to make it so that address 0 was readable,
and assigned a block of nul bytes. Hence

struct *foo = NULL;

meant that foo.member had a value of zero. Talk about a way to
produce system dependant bugs... :-)

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Floyd L. Davidson

2005-06-24, 2:48 am

"David Schwartz" <davids@webmaster.com> wrote:
>"Chris Friesen" <cfriesen@nortel.com> wrote in message
>news:11bm9u56v2vp431@corp.supernews.com...
>
>
> The NULL pointer value is never a valid address. For example, the return
>value of 'malloc' or 'new' cannot test equal to NULL.


When malloc *fails*, it returns NULL.

A pointer set to NULL *must* be a valid pointer to the degree
that it can be used in comparisons... it just can't compare
equal to the address of any object or function.

"the resulting pointer, called a null pointer, is
guaranteed to compare unequal to a pointer to any
object or function."
-- C99 Standard

>
> That's not an exception. The C standard does not say what happens when
>you derefence a NULL pointer because that is not legal. Anything can happen,
>and the standard is satisfied.
>
> DS


--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Ari Lukumies

2005-06-24, 7:52 am

Floyd L. Davidson wrote:
> Technically, if I've got this right, dereferencing p above would
> be legal C (which will probably get a segmentation fault,
> because it is an invalid address), while dereferencing p that is
> assigned a /null/ /pointer/ /constant/ value would be undefined
> behavior (and as noted, there is no wrong result).


Technically, a NULL pointer is not required to have its value as zero,
as well as an infinity value may or may not be represented by a bit
pattern or another. It's just common practice to use 0 and NULL
intermixed, and most (if not all) compilers rely on that assumption.


Syntactic assignment and numerical assignment depend on what semantics
the parser is using.
[vbcol=seagreen]

You /can/ have a valid pointer of address zero. However, you must be
careful of what you do with it. Most protected operating systems will
trap it, but MS-DOS, for example, will tolerate with it. Here, it's
not a question of the language, but of the operating system.
[vbcol=seagreen]
> Some platforms used to make it so that address 0 was readable,
> and assigned a block of nul bytes. Hence
>
> struct *foo = NULL;
>
> meant that foo.member had a value of zero. Talk about a way to
> produce system dependant bugs... :-)


Even some systems accept a NULL pointer, due to the construction of
their runtime memory structure (for example, Tandem Guargian OS). In
some systems, it's impossible to do I/O without a NULL pointer
allowation, at least in some situations.

-atl-
--
A multiverse is figments of its own creations
Andrei Voropaev

2005-06-24, 6:00 pm

On 2005-06-24, Ari Lukumies <ari.lukumies@gmail.com> wrote:
> Floyd L. Davidson wrote:
>
> Technically, a NULL pointer is not required to have its value as zero,
> as well as an infinity value may or may not be represented by a bit
> pattern or another. It's just common practice to use 0 and NULL
> intermixed, and most (if not all) compilers rely on that assumption.


Oh well. The above statement might cause lots of problems for all the
programs that have

if(!ptr) printf("Ptr is NULL");




--
Minds, like parachutes, function best when open
Floyd L. Davidson

2005-06-24, 6:00 pm

Ari Lukumies <ari.lukumies@gmail.com> wrote:
>Floyd L. Davidson wrote:
>
>Technically, a NULL pointer is not required to have its value as
>zero,


Well, I'm glad that you read previous articles (mine and others)
and did figure that out... :-)

Or were you just restating the obvious?

>as well as an infinity value may or may not be represented
>by a bit pattern or another. It's just common practice to use 0
>and NULL intermixed, and most (if not all) compilers rely on
>that assumption.


We went through that a few articles back, *in detail*.

>
>Syntactic assignment and numerical assignment depend on what
>semantics the parser is using.


I don't understand your point. (I did understand what he was
saying though... even if the wording might not be exactly
correct.)

>
>You /can/ have a valid pointer of address zero. However, you
>must be careful of what you do with it. Most protected operating
>systems will trap it, but MS-DOS, for example, will tolerate
>with it. Here, it's not a question of the language, but of the
>operating system.


As has been noted previously, Standard C doesn't say anything
about what is or not a "valid pointer". It is always OS
specific as to whether address 0 is valid, and equally OS
specific as to what happens when an invalid address is used.

However, a /null/ /pointer/ is something specifically defined by
the compiler in compliance with the Standard. And dereferencing
a /null/ /pointer/ is undefined behavior, which makes the
*entire* *program* invalid (as far as the C Standard is concerned).

>
>Even some systems accept a NULL pointer, due to the construction


I'm not sure what you mean by "accept". Every implementation of
Standard C *must* accept comparisons using a /null/ /pointer/,
but as noted dereferencing a /null/ /pointer/ is undefined
behavior.

>of their runtime memory structure (for example, Tandem Guargian
>OS). In some systems, it's impossible to do I/O without a NULL
>pointer allowation, at least in some situations.


What do you mean by "a NULL pointer allowation"??

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Floyd L. Davidson

2005-06-24, 6:00 pm

Andrei Voropaev <avorop@mail.ru> wrote:
>On 2005-06-24, Ari Lukumies <ari.lukumies@gmail.com> wrote:
>
>Oh well. The above statement might cause lots of problems for all the
>programs that have
>
>if(!ptr) printf("Ptr is NULL");
>
>


But, regardless of what the bit pattern for a /null/ /pointer/ is,
it is *guaranteed* to compare equal to 0.

It is not an *assumption* that 0 and NULL can be intermixed.
In a pointer context, 0 is defined as a /null/ /pointer/ /constant/,
and *will* be converted by the compiler to a /null/ /pointer/.

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Gordon Burditt

2005-06-24, 6:00 pm

>> Technically, a NULL pointer is not required to have its value as zero,
>
>Oh well. The above statement might cause lots of problems for all the
>programs that have
>
>if(!ptr) printf("Ptr is NULL");
>
>


No, it won't. That statement might generate the code:

... ptr is a local variable kept in r34 ...
cmpl r34,#0xdeadbeef
jne .L735
... call printf ...
..L735:

so it will work fine if NULL is not represented as all-bits-zero.

The null pointer is not guaranteed to be represented as 0xdeadbeef,
even on systems where pointers are 32 bits.

Gordon L. Burditt
David Schwartz

2005-06-24, 6:00 pm


"Chris Friesen" <cfriesen@nortel.com> wrote in message
news:11bmgsehjp8ft27@corp.supernews.com...

> Consider the following thought experiment for machines where the NULL
> pointer value is all zeros.
>
> I have some valid object.
> I cause the system to map memory at the zero address.


How, in the C language, can you do this?

> I create a pointer with the address of zero.
> I copy my valid object to the pointer with the zero address.
>
> If I then compare a NULL pointer with the pointer to this object, from
> what you've said the result of that comparison should be false.
>
> I suspect that the result will be true on many systems.
>
> Note that I am not saying that this is correct, only that I suspect many
> systems are not strictly adhering to the rules.


There are very few rules once you start casting integers to pointers.

DS


David Schwartz

2005-06-24, 6:00 pm


"Floyd L. Davidson" <floyd@barrow.com> wrote in message
news:87u0jompow.fld@barrow.com...

> "David Schwartz" <davids@webmaster.com> wrote:
>
> When malloc *fails*, it returns NULL.


Exactly. So the NULL pointer cannot be returned as a valid address from
'malloc'.

> A pointer set to NULL *must* be a valid pointer to the degree
> that it can be used in comparisons... it just can't compare
> equal to the address of any object or function.


You must be able to load it into a pointer and compare it without
faulting.

DS


David Schwartz

2005-06-24, 6:00 pm


"Andrei Voropaev" <avorop@mail.ru> wrote in message
news:3i2lssFjhackU1@individual.net...

> On 2005-06-24, Ari Lukumies <ari.lukumies@gmail.com> wrote:


[vbcol=seagreen]
>
> Oh well. The above statement might cause lots of problems for all the
> programs that have
>
> if(!ptr) printf("Ptr is NULL");


Nope, because "!ptr" is (almost) equivalent to "ptr!=0", which is
(almost) equivalent to "ptr != (void *) 0", which is (almost) equivalent to
"ptr!=NULL".

DS


David Schwartz

2005-06-24, 6:00 pm


"Ari Lukumies" <ari.lukumies@gmail.com> wrote in message
news:aRTue.8520$To6.6427@reader1.news.jippii.net...

> Technically, a NULL pointer is not required to have its value as zero, as
> well as an infinity value may or may not be represented by a bit pattern
> or another. It's just common practice to use 0 and NULL intermixed, and
> most (if not all) compilers rely on that assumption.


That all depends upon what you mean by "have its value as zero". What
does it mean for a *pointer* to have its value as zero? There are two
possible meanings.

DS


Chris Friesen

2005-06-24, 6:00 pm

David Schwartz wrote:
> "Chris Friesen" <cfriesen@nortel.com> wrote in message
[vbcol=seagreen]
> How, in the C language, can you do this?


Not C, but POSIX.

void *ptr = mmap(0,size,PROT_WRITE|PROT_READ, MAP_FIXED|MAP_ANONYMOUS,0,0);

> There are very few rules once you start casting integers to pointers.


I realize this. I was simply basing this off an earlier statement that
it was a valid way to assign a numerically zero value to a pointer
without triggering the special behaviour of NULL/0.

Chris
Pascal Bourguignon

2005-06-24, 6:00 pm

Andrei Voropaev <avorop@mail.ru> writes:

> On 2005-06-24, Ari Lukumies <ari.lukumies@gmail.com> wrote:
>
> Oh well. The above statement might cause lots of problems for all the
> programs that have
>
> if(!ptr) printf("Ptr is NULL");
>
>


Of course. If you use !ptr, then ptr is not a pointer, it's a boolean.


--
__Pascal Bourguignon__ http://www.informatimago.com/
The rule for today:
Touch my tail, I shred your hand.
New rule tomorrow.
Sean Burke

2005-06-24, 6:00 pm


umagnum338@netscape.net writes:

> Hi,
>
> encountered something that I'm hoping those more experienced than I can
> answer. At work, I was working my way through a serial testing program
> that was written a while back and wouldn't build without some help.
>
> While trouble shooting I noticed that the program was bailing right
> from the beginning because main() looked like this:
>
> /* include */
>
> int main( int argc, char *argv[] ) {
> ModemObject M;
>
> if( argc == 1 ) {
> printf( "You must specify a file; e.g. /dev/ttyS0\n" );
> return 1;
> }
> // continue
> return 0;
> }


Aside from all the interesting discussion regarding null pointers,
does the C runtime flush stdio buffers if main() returns, instead of
calling exit()? Does the C++ runtime also make this guarantee?

-SEan

Floyd L. Davidson

2005-06-24, 6:00 pm

Sean Burke <foobar@mystery.org> wrote:
>
>Aside from all the interesting discussion regarding null pointers,
>does the C runtime flush stdio buffers if main() returns, instead of
>calling exit()? Does the C++ runtime also make this guarantee?


Read the man page for exit(3). It's explicit that buffers are
flushed.

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Floyd L. Davidson

2005-06-24, 6:00 pm

"David Schwartz" <davids@webmaster.com> wrote:
>"Floyd L. Davidson" <floyd@barrow.com> wrote in message
>news:87u0jompow.fld@barrow.com...
>
>
> Exactly. So the NULL pointer cannot be returned as a valid address from
>'malloc'.


What is your definition of "valid address"? It is a valid address that
indicates malloc failed, no?

Your statement that "the return address ... cannot test equal to NULL" is
not correct.

>
> You must be able to load it into a pointer and compare it without
>faulting.


Well that's what I just said. Should we repeat it again?

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Floyd L. Davidson

2005-06-24, 6:00 pm

"David Schwartz" <davids@webmaster.com> wrote:
>"Chris Friesen" <cfriesen@nortel.com> wrote in message
>news:11bmgsehjp8ft27@corp.supernews.com...
>
>
> How, in the C language, can you do this?


The C language doesn't have a problem with it, but the OS probably
will.

int x = 0;
int *p = x;

If the OS thinks memory at address 0 is okay, the p is a valid
pointer to that memory.


Certainly, but 0 is *not* a valid address on those systems.
[vbcol=seagreen]
>
> There are very few rules once you start casting integers to pointers.
>
> DS


--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Floyd L. Davidson

2005-06-24, 6:00 pm

"David Schwartz" <davids@webmaster.com> wrote:
>"Andrei Voropaev" <avorop@mail.ru> wrote in message
>news:3i2lssFjhackU1@individual.net...
>
>
>
>
> Nope, because "!ptr" is (almost) equivalent to "ptr!=0", which is
>(almost) equivalent to "ptr != (void *) 0", which is (almost) equivalent to
>"ptr!=NULL".


They are all *precisely* equivalent, with an ISO/ANSI Standard C
compiler.

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Floyd L. Davidson

2005-06-24, 6:00 pm

Pascal Bourguignon <pjb@informatimago.com> wrote:
>Andrei Voropaev <avorop@mail.ru> writes:
>
>
>Of course. If you use !ptr, then ptr is not a pointer, it's a boolean.


The result of the expression "!ptr" is a boolean, but ptr is
still a pointer. That is precisely the same as "ptr == 0".

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Brian Raiter

2005-06-24, 6:00 pm


> The C language doesn't have a problem with it, but the OS probably
> will.
>
> int x = 0;
> int *p = x;
>
> If the OS thinks memory at address 0 is okay, the p is a valid
> pointer to that memory.


It is precisely the C language that has a problem with the above. The
program is attempting to assign a pointer a non-pointer value.
According to the ANSI C standard, this invokes undefined behavior.

b

Floyd L. Davidson

2005-06-25, 2:49 am

blr@drizzle.com (Brian Raiter) wrote:
>
>It is precisely the C language that has a problem with the above. The
>program is attempting to assign a pointer a non-pointer value.
>According to the ANSI C standard, this invokes undefined behavior.


The Standard specifically says the result is *implementation*
*defined*, which means the syntax is correct, the result do not
cause undefined behavior, but as I note the OS may not accept it
as a useful address. (See Secstion 6.3.2.3, paragraphs 5 and 6.
You've confused that with conversion *from* a pointer to an
integer, which might indeed be undefined behavior.)

BTW, here are two other means of generating a valid pointer, as
far a the C Standard is concerned, with an bits are 0 pattern:

int *p1 = (int *) 0; /* does not generate a /null/ /pointer/ */
int *p2;

memset(&p2, 0, sizeof p2); /* does not generate a /null/ /pointer/ */


--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Tim Woodall

2005-06-25, 5:50 pm

On Fri, 24 Jun 2005 18:41:32 -0800,
Floyd L. Davidson <floyd@barrow.com> wrote:
>
> int *p1 = (int *) 0; /* does not generate a /null/ /pointer/ */

No, this does give a null pointer.

C99 6.3.2.3

#3 "An integer constant expression with the value 0, ..., is called a null
pointer constant. If a null pointer constant is converted to a pointer
type, the resulting pointer, called a null pointer, ..."


#5 "An integer may be converted to any pointer type. Except as
previously specified, ..."

This explicitly states that (as previously stated) integer _constant_
expression with value 0 is always converted to a null pointer.

Note this also means that:

int *p1 = (int*)(2+3-5);

is also a valid null pointer.



In the following code:

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

You must include the (void*) cast because NULL might be defined as 0 (or
even (2+3-5) ) and printf is a variadic function so NULL could then be
treated as an integer in this context.


Tim.

--
God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
and there was light.

http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/
Tim Woodall

2005-06-25, 5:50 pm

On 23 Jun 2005 22:45:00 GMT,
Nils Weller <me@privacy.net> wrote:
>
> It may be interesting to note that NULL is a place where C is more type-
> safe than C++; Since C++ does not implicitly convert void pointer
> expressions to non-void pointer expressions, NULL has to be an ``integer
> constant expression'' in C++, while it can be, and frequently is defined
> as, ``such an expression cast to type void *'' in C. In other words, the
> C++ definition of NULL usually looks like this:
>
> #define NULL 0
>
> ... whereas the C definition usually looks like this:
>
> #define NULL ((void *)0)


The standard explicitly allows implementations to define NULL as any
valid null pointer constant. And 0 is a valid null pointer constant in C
(as is any integer constant expression of value 0)

So a C implementation can perfectly validly define NULL as 0.

>
> This means that, given such a definition, any use of NULL in a context
> where a pointer expression is not permitted will yield a compiler
> diagnostic in C, but not in C++.


It might give a diagnostic, but then again it might not, depending on
what the implementation has defined NULL as.

>
> Another interesting implication that comes to mind is the fact that
> the C++ version is more likely to break code that passes an uncast NULL
> to a variadic function;
>
> (void) execl(prog, arg1, arg2, ..., NULL); /* should be (char *)NULL! */
>
> This code is invalid because execl() expects a list of ``char *''
> arguments, but since it is a variadic function, the compiler cannot
> know the expected argument type a priori and has to trust that you
> always pass arguments of the right type. Now, if NULL is defined as a
> void pointer expression, the code will work correctly. But if it is
> defined as 0 and the size of an ``int'' differs from that of a
> ``char *'', and/or these types are simply passed passed to the function
> in different ways, or some other such problem occurs, the code is more
> likely to break - thus making the bug visible.
>

Again, you still need the cast in C. And although in this particular
case you don't need the (char*) cast if NULL is defined as ((void*)0)
had this been a variadic function expecting an int* you would always
require the (int*) cast in both C and C++

> Both definitions have advantages and disadvantages.
>

ISTM that C has all the disadvantages of C++ but with extra traps for
the unwary who start assuming that NULL is always ((void*)0).

Tim.

--
God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
and there was light.

http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/
Floyd L. Davidson

2005-06-25, 5:50 pm

Tim Woodall <devnull@woodall.me.uk> wrote:
>On Fri, 24 Jun 2005 18:41:32 -0800,
> Floyd L. Davidson <floyd@barrow.com> wrote:
>No, this does give a null pointer.


You are correct. I was sleeping... :-) And thinking it had to
be converted to a pointer to void, but that is ridiculous.

Sorry.

>C99 6.3.2.3
>
>#3 "An integer constant expression with the value 0, ..., is called a null
>pointer constant. If a null pointer constant is converted to a pointer
>type, the resulting pointer, called a null pointer, ..."
>
>#5 "An integer may be converted to any pointer type. Except as
>previously specified, ..."
>
>This explicitly states that (as previously stated) integer _constant_
>expression with value 0 is always converted to a null pointer.
>
>Note this also means that:
>
>int *p1 = (int*)(2+3-5);
>
>is also a valid null pointer.
>
>In the following code:
>
>printf("%p\n", (void*)NULL);
>
>You must include the (void*) cast because NULL might be defined as 0 (or
>even (2+3-5) ) and printf is a variadic function so NULL could then be
>treated as an integer in this context.
>
>Tim.
>
>--
>God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
>and there was light.
>
> http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/


--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
Tim Woodall

2005-06-25, 5:50 pm

On Thu, 23 Jun 2005 14:49:57 +0300,
Ari Lukumies <ari.lukumies@gmail.com> wrote:
> umagnum338@netscape.net wrote:
>
> Some of the includes redefined NULL?
>
> void *p = NULL;
> void *p = 0;
>
> should yield the same (since, by definition, NULL is defined as
> (void*)0) - although the latter is recommended in C++ circles.

No. In C NULL is (implementation) defined as any valid null pointer
constant. 0 and ((void*)0) are the two most common.

In C++ only integer constant expressions with value 0 are null pointer
constants. ((void*)0) is NOT a valid definition for NULL although 0 and
0L both are.

Tim.

--
God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
and there was light.

http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/
Nils Weller

2005-06-25, 5:50 pm

In article <slrndbqptj.c63.devnull@feynman.home.woodall.me.uk>,
Tim Woodall wrote:
> On 23 Jun 2005 22:45:00 GMT,
> Nils Weller <me@privacy.net> wrote:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^[vbcol=seagreen]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^[vbcol=seagreen]
>
> The standard explicitly allows implementations to define NULL as any
> valid null pointer constant. And 0 is a valid null pointer constant in C
> (as is any integer constant expression of value 0)
>
> So a C implementation can perfectly validly define NULL as 0.


I didn't say a C implementation cannot do this, right? I said that it
can be (but doesn't have to be!) defined as such an expression cast to
type void * in C, while it cannot in C++, and that many C
implementations choose to use this definition of NULL. This is why I
used the words ``frequently'' and ``usually'' rather than ``always'' in
the quoted paragraph above.

>
> It might give a diagnostic, but then again it might not, depending on
> what the implementation has defined NULL as.


Which is exactly why I put a ``given such a definition'' (meaning:
``((void *)0)'' into the above paragraph. Given this definition of NULL:

#define NULL ((void *)0)

.... any use of NULL in a context where a pointer expression is not
permitted will yield a compiler diagnostic in C.

> Again, you still need the cast in C. And although in this particular
> case you don't need the (char*) cast if NULL is defined as ((void*)0)
> had this been a variadic function expecting an int* you would always
> require the (int*) cast in both C and C++


True, but again, I didn't say that passing an uncast NULL is not a bug.
I only said that a definition of 0 is ``more likely'' to break such
code. I didn't say that it guarantees breaking such code.

> ISTM that C has all the disadvantages of C++ but with extra traps for
> the unwary who start assuming that NULL is always ((void*)0).


I didn't make such an assumption.

--
Nils R. Weller, Bremen / Germany
My real email address is ``nils<at>gnulinux<dot>nl''
.... but I'm not speaking for the Software Libre Foundation!
Ari Lukumies

2005-06-25, 8:47 pm

Tim Woodall wrote:
> No. In C NULL is (implementation) defined as any valid null pointer
> constant. 0 and ((void*)0) are the two most common.
>
> In C++ only integer constant expressions with value 0 are null pointer
> constants. ((void*)0) is NOT a valid definition for NULL although 0 and
> 0L both are.


I stand corrected.

-atl-
--
A multiverse is figments of its own creations
Brian Raiter

2005-06-27, 5:53 pm

>> It is precisely the C language that has a problem with the
>
> The Standard specifically says the result is *implementation*
> *defined*, which means the syntax is correct, the result do not
> cause undefined behavior, but as I note the OS may not accept it as
> a useful address. (See Secstion 6.3.2.3, paragraphs 5 and 6.
> You've confused that with conversion *from* a pointer to an integer,
> which might indeed be undefined behavior.)


My apologies. You'd think that it would be the other way round,
wouldn't you? Apparently I did.

b
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com