Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!lll-lcc!styx!ames!rutgers!gatech!mcnc!rti!dg_rtp!throopw From: throopw@dg_rtp.UUCP (Wayne Throop) Newsgroups: comp.lang.c Subject: Re: passing NULL to functions Message-ID: <1817@dg_rtp.UUCP> Date: Sat, 2-May-87 17:19:08 EDT Article-I.D.: dg_rtp.1817 Posted: Sat May 2 17:19:08 1987 Date-Received: Sun, 3-May-87 06:47:25 EDT References: <150@sds.UUCP> <1129@ius2.cs.cmu.edu> <7974@utzoo.UUCP> Lines: 63 > henry@utzoo.UUCP (Henry Spencer) >> Are you saying that you are not guarenteed sizeof(char *) == sizeof(int *) >> sizeof(long *) == sizeof(whatever *)? ... > Precisely. The major reason this arises is that on word-addressed machines, > e.g. Data General systems (unless they've changed since I knew them), the > "normal" pointer format points only to a word, and there are no spare bits > in the pointer that could be used to point to a byte within the word. (The > use of such spare bits is a major reason why the representation of "char *" > can differ from the representation of "int *" even on machines where the > sizes of the two pointers are the same.) There is just no way to point to > a character except to define a longer kind of pointer to hold the extra > information. This is all perfectly correct, except that DG machines aren't examples of this phenomenon, quite. DG machines' main pointer format is a pointer to a 16-bit word. However, it has a "spare bit" in the form of an "indirect bit", which indicates that this pointer points to a pointer to the desired word. This indirect bit is almost never used, and IS never used by the C compiler. And so, instructions were introduced (during the evolution from the original Nova architecture to the current MV architecture) which manipulated pointers to 8-bit bytes, with no indirect bit. They thus effectively cover the same address space, and both (on an MV) fit into 32 bits. As a later addition, instructions that reference individual bits were added, and the pointers here cannot fit into 32 bits. They occupy 64 bits (which is somewhat bigger than strictly necessary, but it was the format that was chosen, for various reasons). Nevertheless, most instructions naturally deal with 16-bit granular pointers, and only character-manipulation instructions deal with 8-bit granular pointers. So there is a strong motive for using the two different pointer formats for their respective purposes, that is, to indicate the addresses of characters by 8-bit granular pointers (most often called bytepointers), and the addresses of everything else by 16-bit granular pointers (called wordpointers). Again, both of these pointer formats fit into 32 bits, but the bits are interpreted somewhat differently. Thus, it is important in DGs implementation of C to use pointers in a type-correct way. The moral is: ALWAYS pass the correct pointer type. If you have a compiler that implements prototypes, you can pass an uncast NULL. If you do not, you must ALWAYS cast NULL to the appropriate type before passing. If you don't do this, your code will not be portable, and that is that. There is NOTHING that a compiler implementor can do to help you on all machines if you make this coding mistake. Making NULL ((void *)0) won't help in the general case. And that is all there is to that. (Of course, making NULL be ((char *)0) is an even worse faux-pas. There is no guarantee that casting a null pointer of one type to another type gives sensible results, though it generally does.) (Further, the incorrect, widespread and apparently incorrigable belief that NULL should be #defined to be something other than 0 causes me personally never to code NULL, but always a correctly cast 0. Just a personal prejudice of mine.) -- "Mowe bwiefing?" "More briefing!" --- Elmer & Daffy -- Wayne Throop !mcnc!rti!dg_rtpW *)0)a