Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watmath!clyde!rutgers!ames!ucbcad!ucbvax!decvax!decwrl!sun!gorodish!guy From: guy@gorodish.UUCP Newsgroups: news.software.b,comp.lang.c Subject: Re: News for Xenix on PC AT ? Message-ID: <17245@sun.uucp> Date: Thu, 23-Apr-87 13:43:08 EST Article-I.D.: sun.17245 Posted: Thu Apr 23 13:43:08 1987 Date-Received: Sat, 25-Apr-87 07:35:22 EST References: <18346@ucbvax.BERKELEY.EDU> <145@sds.UUCP> <17005@sun.uucp> <146@sds.UUCP> Sender: news@sun.uucp Lines: 118 Xref: utgpu news.software.b:511 comp.lang.c:1801 > Why is "if (charptr == 0)" NOT identical to "if ((int)charptr == 0)" ??? From K&R, 7.7 "Equality operators": A pointer may be compared to an integer, but the result is machine dependent unless the integer is the constant 0. A pointer to which 0 has been assigned is guaranteed not to point to any object, and will appear to be equal to 0; in conventional usage, such a pointer is considered to be null. So a C compiler *must* properly handle "if (charptr == 0)". It MUST not do an integer comparison if that would give a different result from a pointer comparison. In effect, it must convert the "0" to a character pointer of the appropriate type. On the other hand, *your* example converts the *pointer* to an *integer* before doing the comparision, which is NOT correct. > In fact, since we are comparing apples (char *'s) to oranges (int's), > a cast is called for and a good, conscientious programmer would perform > the cast themself. Wrong. The C language lacks a token like Pascal's "nil", so a constant expression with the value 0 must do double duty as a representation of a null pointer. The statement if (charptr == 0) is comparing "charptr" to a null pointer, not to the integer 0. > Furthermore, "if (!charptr)" is not correct on all architectures: Yes, it is. > I've heard tell of an implementation of C where NULL was > 0xffffffff -- the simple "if (!charptr)" fails in this case. If you mean "an implementation of C where 'NULL' is defined to be '0xffffffff'", you haven't heard of such an implementation, because it does not exist. What you heard of is an implementation of some other programming language, created by the implementor, which said implementor was under the delusion was C. If you mean "an implementatiion of C where a null pointer is represented by the same bit pattern that the integral constant '0xffffffff' has", then "if (!charptr)" MUST NOT FAIL. In a C implementation the statement "if (!charptr)" MUST compile into something that compares the variable "charptr" against a null pointer; if this means it must compare into a comparison of the bit pattern of "charptr" against the bit pattern represented by "0xffffffff", then so be it. > Coding the above as "if (charptr == (char *)NULL)" saves you from the > "queer machine"; No, it doesn't. It may save you against the turkey who didn't understand C when they implemented the compiler for that machine, but the right thing to do here is bitch that the alleged C implementation for that machine isn't implementing C. > it is also more correct in that it explicitly states what you desire I desire to compare "charptr" with a null pointer of the appropriate type; according to K&R (and the ANSI C draft), "if (charptr == 0)" quite explicitly requests that comparison. > and is more portable. Again, it is NOT more portable, unless you consider portability to incorrect C implementations to be important (I don't; I consider it more important to get those implementations fixed!). > Actually, if NULL is *correctly* defined in stdio.h as "(char *)0" > (NULL being the value that malloc() returns on error, NULL *should* have > type char *), Defining NULL as "(char *)0" is NOT correct. Other routines than "malloc" return NULL on errors, such as the UNIX routine "getpwent"; singe "getpwent" does not return a character pointer, it can hardly return "(char *)0". It seems to be a common misconception that the fragment if (foo == 0) or the expression foo = 0 must be implemented by testing whether all the bits representing "foo" are 0, or by clearing all the bits in "foo", respectively. This is simply not the case. For those of you still having trouble with this in the case where "foo" is a pointer, consider the case where "foo" is a floating-point number. There may be a machine on which floating-pointer zeroes do not have an all-zero bit pattern, and on those machines the aforementioned comparison and assignment cannot be implemented in the aforementioned fashion. Even if floating-point zeroes *do* have an all-zero bit pattern, consider the fragment if (foo == 1) or the expression foo = 1 Must these test whether all bits of "foo" are zero except for the low-order one, which must be one, or clear all bits of "foo" except for the low-order one, which is set? Of course not. If a not-necessarily-compatible successor to C were being designed, I'd recommend that they get rid of the pointer/array interchangability rules and add a token that represents a null pointer; both of those seem to cause C to behave in ways not obvious to novices.