This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: GCC headers and DJGPP port (OT)


I maintain that C++ is correct, and IN CONSONANCE with ANSI C, in not
allowing NULL to be defined as ((void *)0)

In support of this assertion, I am quoting three paragraphs, one from MODERN
ANSI/ISO STANDARDS for C and C++, one from an EQUIVALENTLY modern and ANSI
conforming book:

ISO/IEC 14882:1998(E) [ C++ Standard ]

"4.10 Pointer conversions

1 A null pointer constant is an integral constant expression (5.19) rvalue
of integer type that evaluates to zero. A null pointer constant can be
converted to a pointer type; the result is the null pointer value of that
type and is distinguishable from every other value of pointer to object or
pointer to function type. Two null pointer values of the same type shall
compare equal. The conversion of a null pointer constant to a pointer to
cv-qualified type is a single conversion, and not the sequence of a pointer
conversion followed by a qualification conversion (4.4)"

ANSI C Edition of "The C Programming Language" by Kernighan and Ritchie
Appendix A: Reference Manual

"A6.6 Pointers and integers

[third paragraph]

An integral constant expression with value 0, or such an expression cast to
type void *, may be converted, by a cast, by assignment, or by comparison,
to a pointer of any type. This produces a null pointer that is equal to
another null pointer of the same type, but unequal to any pointer to a
function or object."

same book p. 102
[paragraph near the center of the page]

"Pointers and integers are not interchangeable. Zero is the sole exception:
the constant zero may be assigned to a pointer, and a pointer may be
compared with the constant zero. The symbolic constant NULL is often used in
place of zero, as a mnemonic to indicate more clearly that this is a special
value for a pointer. ...."

------------

C++ legimately takes away the EXTRA PRIVILEGE of prepending (void *) to 0,
because it doesn't serve any purpose except to generate warnings when NULL
is assigned to non-pointer variables. There was a strong reason to take away
this "no sand in the gas tank" privilege -- as outlined in a mail by
somebody else on the subject, by allowing an implicit cast from (void *) to
(some-type *) we are allowing blind creation of type information (the
original author expresses the point better).

Both C and C++ (ANSI/ISO) give the special status to 0 and compile time
integer expressions evaluating to 0. That special status is that the rvalue
can be used as a null pointer.

So, why on earth would one want

However, Linus has pointed out a seemingly legitimate reason to be able to
prepend (void *) to 0. That is, overloading problems. Well, it is something
to be thought over in depth. The complaint is that you cannot get overload
resolution between "void foo(int);" and "void foo(int *);" if you call
"foo(NULL)". But then, what about the case where you have "void foo(char
*);" and "void foo(int *);"? Even if (void *)0 were allowed, how would the
C++ compiler distinguish between the two in a call to "foo(NULL)". Allowing
(void *) only postpones this problem. Whether it is solvable IN GENERAL
without the compiler reading the programmer's mind or not, is not clear to
me. In my (strong) opinion, the language design is more elegant without the
(void *) allowance.

------------

Yes, I agree that whether one wants to use 0 in code, or use NULL defined as
0, is purely a matter of personal taste. The visual aid provided by NULL is
helpful but not sufficient to NECESSIATE its use. One cannot look at "1" and
say whether it is being passed to a short, int, char, or long? Reiterate: it
is okay to use NULL instead of 0 but it is purely a matter of taste.

------------

Unlike the ISO C++ standard, the C standard is prohibitively expensive for
me to keep on my desk, which is why I quoted from the ANSI edition of K&R
(which is quite different from K&R C). I would like to state that I have
NEVER written a non-prototyped C function. I endeavour to use the most
modern standardized editions of languages and software.

------------

No offense intended to anybody, it is easy and understandable to presume
that I am a complete novice or an old-timer sticking to prototypes. But then
I suppose being called silly and stupid (although in private) does allow me
to do a bit of uppercasing! :-)

Cheers,
Anjul.

-----Original Message-----
From: Linus Torvalds [mailto:torvalds@transmeta.com]
Sent: Sunday, July 23, 2000 1:37 PM
To: Anjul
Subject: Re: GCC headers and DJGPP port (OT)




On Sun, 23 Jul 2000, Anjul wrote:
>
> I personally hate using NULL anywhere in C/C++ code.

You're being silly.

> 0 has special status in C (and also I presume C++). I don't have K&R with
me
> now, but if you search the index (for NULL (?)), you will find a paragraph
> that goes like (can send you the exact pp. later if you wish):

Note that K&R C is broken. It doesn't have proper type-checking for
functions etc, and ANSI C is the only one that really makes sense to use
for the last 10 years or so.

But yes, 0 is special. However, it should NOT be used.

> Therefore, (void *)0 is quite unnecessary. 0 would serve the same purpose.

No.

Using a plain "0" is bad. It means that the following non-sensical code
will compile without warnings:

	int i = NULL;

And in the case of C++, the problem becomes even worse, as the type of the
operand determines what you should do with overloading etc.

Thus ((void *)0) is a _lot_ better than using 0.

And ANSI C has allowed it from the beginning.

> Perhaps, one use of (void *)0 would be to restrict its comparison or
> assignment to int, char, long, ... types. I don't see this advantage as
> significant or important. To try to stop programmers from writing "int
> i=NULL;" is in the direction of trying to stop car-owners from putting
sand
> in their gas-tanks.

Go on playing with your K&R compiler, go on not using prototypes and type
checking. Trust me, good programmers do NOT ignore the importance of
type-checking. They may know how to avoid it on purpose, but it should not
be avoided by stupidity.

		Linus

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]