Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!utcsri!greg From: greg@utcsri.UUCP Newsgroups: news.software.b,comp.lang.c Subject: Re: News for Xenix on PC AT ? Message-ID: <4658@utcsri.UUCP> Date: Fri, 24-Apr-87 10:09:34 EST Article-I.D.: utcsri.4658 Posted: Fri Apr 24 10:09:34 1987 Date-Received: Sat, 25-Apr-87 07:17:23 EST References: <18346@ucbvax.BERKELEY.EDU> <145@sds.UUCP> <17005@sun.uucp> <146@sds.UUCP> Reply-To: greg@utcsri.UUCP (Gregory Smith) Organization: CSRI, University of Toronto Lines: 88 Xref: utgpu news.software.b:510 comp.lang.c:1800 Summary: In article <146@sds.UUCP> dave@sds.UUCP (dave schmidt x194) writes: >Why is "if (charptr == 0)" NOT identical to "if ((int)charptr == 0)" ??? >This would not work on a machine where sizeof(char *) > sizeof(int). >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. Furthermore, "if (!charptr)" is not correct on all >architectures: I've heard tell of an implementation of C where NULL was >0xffffffff -- the simple "if (!charptr)" fails in this case. Even if NULL is 0xCAFEF00D, the !ptr method should still work. The constant '0' may be used in a pointer context in a very few cases ( assignment, initialization, comparison, opposite side of a : from a pointer ), and in each of these cases, the constant is taken to mean a null pointer of the appropriate type. When a pointer appears in conditional context, it is first converted to a comparison with zero. Thus !ptr becomes !(ptr!=0) which becomes ptr==nullptr where nullptr is a constant of the same type as ptr and with the same bit pattern as a null pointer of that type. If the null pattern is indeed zero, the instruction will be coded as test-for-zero. I am not sure whether this is what ANSI says, but I certainly think it should work this way. I have never used a machine where NULL has not been really 0, so I haven't run into a problem here. In any case K&R compilers allow '0' in any pointer context, and do not allow any other int constant without giving at least a warning. Even if a null char * had the value 0xCAFEF00D, it would be erroneous to say "charptr = 0xCAFEF00D". >Coding the above as "if (charptr == (char *)NULL)" saves you from the >"queer machine"; it is also more correct in that it explicitly states what >you desire and is more portable. 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 *), this could be written as >"if (charptr == NULL)". This technique is much less portable. What if I have a structure pointer strp which I want to set to null? I can't say strp=NULL if NULL is incorrectly defined as (char*)0 since I get a type mismatch. I have to say strp=(struct foo*)NULL. What then if NULL is non-zero? I get strp=(struct foo*)(char*)0xCAFEF00D. Suppose the machine requires some pointer casts to convert. Do these casts convert? Suppose there is a different bit pattern for null char*'s and other null pointers. The best way to handle all these problems is to allow the compiler to convert the constant zero to the appropriate null pointer value. There is one little problem with this, that of passing null pointers to functions. A K&R compiler does not know the types of function parameters, so saying foo(0) when foo is expecting a int * won't work. You have to write foo((int*)NULL), which is the same as foo((int*)0). It follows that a compiler must perform casts of the constant zero to a pointer at compile time, by converting it to the appropriate null pointer. >Unfortunately for me, XENIX correctly defines >NULL, leaving me to deal with statements such as: > > int cnt; > char ch, *ptr; > > ptr = NULL; /* this is ok */ > ... > ch = NULL; /* expands to: ch = (char *)0; */ > /* ch = '\0'; is desired */ > ... > if (cnt == NULL) /* expands to: if (cnt == (char *)0) */ > /* i'd settle for if (!cnt) */ > ... The latter two usages of NULL are as you say incorrect. This is a human problem and not a compiler problem. > >Given my #define for NULL, statements of this kind make the compiler >complain (as it should). but it also complains about struct_ptr = NULL. There are other types of pointers than char *. > That point aside, it makes little sense to >me to say that a pointer to a character and a character may be >assigned the same value without a cast someplace. This implicitly >assumes that NULL is #defined as 0, which is an assumption that >good programmers (or should I say "programmers that I regard as good"?) >don't make. Good programmers don't use NULL unless they mean a null pointer. This is simply a matter of discipline. Other than that, they know that NULL is defined as 0 and that they therefore must cast it when passing it to a function. -- ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg Have vAX, will hack...