nwc@cunixc.columbia.edu (Nick Christopher) (08/19/87)
Yes I started the whole thing :-) And I am glad to announce my code runs!!!!! I pulled from all the answers to my question and these were the key ingredients: 1) Use NULL not 0 as often as applicable. 2) use sizeof()'s in malloc()'s and calloc()'s i.e.: char *s,*s2; s2 = "hello"; s = malloc(strlen(s2)+1); strcpy(s,s2); This is will slide through on a VAX but "don't try this at home kiddies", instead: s = malloc((strlen(s2)+1)*sizeof(char)); 3) Make a ".h" file and externally declare ALL your functions so that the return type is clear before a function it called. 4) Compile with the -DLINT_ARGS an clear up all the messages generated. I had problems with free(foo) when foo was a pointer to a structure, free((char *)foo) solved the problem. Actually all of these are basic good programming habits, I was just ignored them since the VAX 8700 I was on was so forgiving.... It served me right! Again, thanks for all the replies to my query, they made the difference. In the imortal words of Bartles&James, "And, Thank you for your support!" /nwc -- "I am the Lorvax. I speak for the machines." ______________________________________________________________________________ nwc%cunixc@columbia, seismo!columbia!cunixc!nwc BITNET: nwcus@cuvma USENET: (seismo | topaz)!columbia!cunixc!nwc
ccs016@ucdavis.UUCP (Patrick Tully) (08/20/87)
> > Yes I started the whole thing :-) And I am glad to announce my code runs!!!!! > > > I pulled from all the answers to my question and these were the key > ingredients: > > 1) Use NULL not 0 as often as applicable. > Why?? Null is defined in stdio as 0. Patrick Tully pstully@ucdavis ucdavis!deneb!ccs016
dhesi@bsu-cs.UUCP (Rahul Dhesi) (08/21/87)
In article <72@cunixc.columbia.edu> nwc@cunixc.columbia.edu (Nick Christopher) writes: > 1) Use NULL not 0 as often as applicable. Actually, I suggest simply casting 0 or NULL, whichever you use, to the correct type when passing it as a parameter. When simply using it for a comparison, a cast is not necessary and either may be used. > 2) use sizeof()'s in malloc()'s and calloc()'s i.e.: [...] > s = malloc((strlen(s2)+1)*sizeof(char)); Purists constantly perpetuate this nonsense. Actually, Kernighan and Ritchie say the following about the sizeof operator on page 126: The size is given in unspecified units called "bytes", which are the same size as a 'char'. Hence sizeof(char) is guaranteed to be exactly 1 and there is no need to multiply by it. Other recommendations made by nwc@cunixc.columbia.edu make a lot of sense. -- Rahul Dhesi UUCP: {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi
jpn@teddy.UUCP (John P. Nelson) (08/21/87)
>>> 1) Use NULL not 0 as often as applicable. > >A cast is necesary for a comparison with large model pointers in >both lattice C and MSC4.0. If you don't cast, then the pointer will >be converted to an int, thereby loosing precision, and very likely >your program will have outlandish behavior. I can't believe how much BAD information gets posted here. If you don't know the answer, then DON'T POST!!!!! This statement (always cast 0 for comparisons) is blatently UNTRUE! It's just plain WRONG! The C language defines that the constant 0 can be assigned to or compared against any pointer! The compiler may need to recognize this as a special case (the standard does not insist that a NULL pointer have a bit pattern of all zeros for instance). The "0" MUST be promoted to a pointer, not the other way around. I can state with authority that there is no BUG as listed above in MSC 4.0 (and it would definitely be a serious BUG). I cannot speak for Lattice compilers. >Using 0 is not usually >portable to compilers where sizeof(int) != sizeof(char *). Using >NULL is guaranteed to work. Someone mentioned why use NULL, since >stdio.h just defines it as 0. Well, both MSC and Lattice, define >NULL as 0 in small model, and 0L in large model. Not everyone >is lucky enough to work on a machine with pointers the size of ints. MORE disinformation! NULL is equivalent to 0, and is not "guaranteed" to work any better than the constant 0. The Lattice and Microsoft compilers evidently define NULL in a way that incorrect use of NULL as a pointer parameter will still function, but it is still INCORRECT and UNPORTABLE! Please do NOT encourage people to program in this incorrect manner! To summarize: when passing a null pointer to a function, you should always cast the 0 or NULL to the proper pointer type. In any other context, you may use 0 or NULL interchangably.
michael@orcisi.UUCP (08/21/87)
> 3) Make a ".h" file and externally declare ALL your functions > so that the return type is clear before a function it called. Given the source file which defines your functions, MSC's -Zg flag will write all the function declarations to the stdout which you just have to redirect into a .h file (and edit the few extraneous lines). > 4) Compile with the -DLINT_ARGS an clear up all the messages > generated. I had problems with free(foo) when foo was a pointer > to a structure, free((char *)foo) solved the problem. We also use -W2 which checks a few extra things like return stmts.
darrylo@hpsrlc.HP.COM (Darryl Okahata) (08/21/87)
In comp.sys.ibm.pc, ccs016@ucdavis.UUCP (Patrick Tully) writes: > > Yes I started the whole thing :-) And I am glad to announce my code runs!!!!! > > > > > > I pulled from all the answers to my question and these were the key > > ingredients: > > > > 1) Use NULL not 0 as often as applicable. > > > > Why?? Null is defined in stdio as 0. > > Patrick Tully > pstully@ucdavis > ucdavis!deneb!ccs016 > ---------- In the large, compact (?), and huge memory models, NULL is defined as 0L, not 0. This makes a BIG difference when trying to pass a NULL pointer to a function (if you don't, your program will probably crash). You can still use 0, as long as you cast it (e.g., "(char *) 0"). Even better, always use casts with NULL (this is not necessary, although it is a good programming practice). -- Darryl Okahata {hplabs!hpcea!, hpfcla!} hpsrla!darrylo CompuServe: 75206,3074 Disclaimer: the above is the author's personal opinion and is not the opinion or policy of his employer or of the little green men that have been following him all day.
rap@oliveb.UUCP (Robert A. Pease) (08/21/87)
In article <698@ucdavis.UUCP> ccs016@ucdavis.UUCP (Patrick Tully) writes: >> >> >> 1) Use NULL not 0 as often as applicable. >> > > Why?? Null is defined in stdio as 0. > >Patrick Tully >pstully@ucdavis >ucdavis!deneb!ccs016 No, NULL is defined as 0 in small, and medium models but is defined as 0L in large and huge models. It does make a difference and it is more portable. -- Robert A. Pease {hplabs|fortune|idi|ihnp4|tolerant|allegra|glacier|olhqma}!oliveb!olivej!rap
jon@amc.UUCP (Jon Mandrell) (08/21/87)
In article <698@ucdavis.UUCP> ccs016@ucdavis.UUCP (Patrick Tully) writes: >> 1) Use NULL not 0 as often as applicable. > Why?? Null is defined in stdio as 0. > NO!!!! If you use large model on a PC, you end up with the wonderful situation of having integers and pointers as a differnet size. On most compilers, it should be the following: #define NULL (char *)0 or #define NULL 0L /* I hate this one! */ If you have a routine that wants to see some arguments, one of which is a pointer: int junk(a,b,c) int a; char *b; int c; And want to pass a 0 for b, DON'T call the function with 0!!!!!! This will screw up your stack offsets. You want to call it with NULL, which is the width of a pointer (large and small model). That is: junk(1, NULL, 2); instead of: junk(1, 0, 2); -------------------- -- Jon Mandrell, Applied Microsystems Corp., (ihnp4!uw-beaver!tikal!amc!jon) Jung vs Ze G. jrer tnl? Jbhyqa'g "Gur N Grnz" gnxr ba n jubyr qvssrerag zrnavat?
chips@usfvax2.UUCP (Chip Salzenberg) (08/21/87)
In article <72@cunixc.columbia.edu>, nwc@cunixc.UUCP writes: > > Yes I started the whole thing :-) And I am glad to announce my code runs!!!!! > > > I pulled from all the answers to my question and these were the key > ingredients: > > 1) Use NULL not 0 as often as applicable. There was a _big_ discussion about this in comp.lang.c. Actually, K&R defines NULL as `an integral value that evaluates to zero'. If you pass NULL as a pointer parameter, YOU HAVE TO CAST IT. This rule is necessary beause some implementations of C for word-addressed machines have different sizes for `char *' and `int *'; on those architectures there is no single integral value which is the same size as all pointers. So, cast, cast, and cast again. Of course, if portability is not important to you -- `NEVER MIND.' :-) > 2) use sizeof()'s in malloc()'s and calloc()'s i.e.: > char *s,*s2; > s2 = "hello"; > s = malloc((strlen(s2)+1)*sizeof(char)); > This is unnecessary. It is always true that sizeof(char) == 1, unless you've #define'ed char to something else, in which case there's trouble in River City. > 3) Make a ".h" file and externally declare ALL your functions > so that the return type is clear before a function it called. This is good advice. NOTE TO ALL FLAME-PRONE READERS: Before you follow up this article, WAIT! Run, don't walk, to comp.lang.c. The people there can answer any C question that has an answer. [Warning: this article has been equipped with a Corbomite device. Anyone directing flames at this article will be hit with counterflames of equal force] -- Chip Salzenberg UUCP: "uunet!ateng!chip" or "chips@usfvax2.UUCP" A.T. Engineering, Tampa Fidonet: 137/42 CIS: 73717,366 "Use the Source, Luke!" My opinions do not necessarily agree with anything.
root@hobbes.UUCP (John Plocher) (08/22/87)
+---- Tim Iverson writes the following in article <3352@zen.berkeley.edu> ---- | Nick Christopher writes: | > 1) Use NULL not 0 as often as applicable. why? | Rahul Dhesi writes: | >Actually, I suggest simply casting 0 or NULL, whichever you use, to | >the correct type when passing it as a parameter. When simply using | >it for a comparison, a cast is not necessary and either may be used. | | A cast is necesary for a comparison with large model pointers in ---------- | both lattice C and MSC4.0. +---- nooooooooo! Rahul is completely correct. The correct definition for NULL is: #define NULL 0 /* NOT 0L !!! */ K&R page 97: "C guarentees that no pointer that validly points at data will contain zero, so a return value of zero can be used to signal an abnormal event ... . We write NULL instead of zero, however, to indicate more clearly that this is a special value for a pointer." Note: zero, not (long) 0 or 0L. The only time one MUST cast NULL is when it is used as a parameter to a function, as in: foo( (char *) NULL ); In this case it is best to cast all pointers AND other non-int values. K&R Page 41: "Implicit arethmetic conversions work much as expected. ... ... for each arethmetic operator, the following sequence of conversion rules is applied:" If one is Convert it to ------ ------------- char int short int float double Then if one is Convert other to Result ------ ---------------- ------ double double double long long long unsigned unsigned unsigned Otherwise the operands must be INT, and the result is INT K&R Page 49 expressly includes == and != as operators. (I'd say more, but a large lightning storm just came up and the systems are shutting down...) -- John Plocher uwvax!geowhiz!uwspan!plocher plocher%uwspan.UUCP@uwvax.CS.WISC.EDU
iverson@cory.Berkeley.EDU (Tim Iverson) (08/22/87)
In article <4291@teddy.UUCP> jpn@teddy.UUCP (John P. Nelson) writes: >>A cast is necesary for a comparison with large model pointers in >>both lattice C and MSC4.0 ... > >I can't believe how much BAD information gets posted here. If you don't >know the answer, then DON'T POST!!!!! Well, this time I guess my fingers did my thinking for me ... I recalled previous postings about this and the fact that in large model NULL is 0L on MSC and Lattice and then added two and two and came up with three - basically that why would they define it to 0L unless they needed to? I cut myself while wielding Occam's razor. When I first saw this mild flame I thought, ah ha!, now I've got 'im. So I wrote a little program to test it out. Well, I'm wrong, John's right, MSC and Lattice both work fine comparing far (32bit) pointers to a short (16bit) 0. Although, in my defense, I must state that this is the first time I've posted such a stupid answer. >To summarize: when passing a null pointer to a function, you should >always cast the 0 or NULL to the proper pointer type. In any other >context, you may use 0 or NULL interchangably. Yes. This is just good programming practice. There are so many habits I've had to force myself into (to maintain portability between unix and msdos) once I started programming in MS-DOS, that I thought casting 0 was required. Sorry for the misinformation. - Tim Iverson iverson@cory.Berkeley.EDU ucbvax!cory.Berkeley.EDU p.s. For those of you who write insulting letters, save it for when we stand face to face ... (say, at dawn w/ bare hands - weapons are for wimps >:-)
mickey@axis.fr (Michael Dance) (08/22/87)
In article <4291@teddy.UUCP>, jpn@teddy.UUCP (John P. Nelson) writes: > >>> 1) Use NULL not 0 as often as applicable. > > > > This statement (always cast 0 for comparisons) is blatently UNTRUE! > It's just plain WRONG! The C language defines that the constant 0 can > be assigned to or compared against any pointer! The compiler may need > to recognize this as a special case (the standard does not insist that > a NULL pointer have a bit pattern of all zeros for instance). The "0" > MUST be promoted to a pointer, not the other way around. > > MORE disinformation! NULL is equivalent to 0, and is not "guaranteed" > to work any better than the constant 0. > > To summarize: when passing a null pointer to a function, you should > always cast the 0 or NULL to the proper pointer type. In any other > context, you may use 0 or NULL interchangably. Despite the assertions of the last poster I would like to point out that there are other systems than MSDOS and other compilers than Lattice and Microsoft. Kernighan and Ritchie introduced NULL (one assumes) for the simple reason that pointers are not the same as interges (nor shorts, longs etc) If you use NULL the correct value will always be used. For exeample, someone in this discussion said that MSC 4.0 uses 0L in Huge model (Large?) and 0 in other models. This is because pointers include a segment address + within segment offset making 4 bytes, in this case passing 0 instead of 0L passes a 2 byte integer value 0, the routine receiving this will look for a 4 byte value of 0, the missing 2 bytes will be the next 2 bytes on the stack (on most m/cs) which could be anything but have little chance of being 0. So for functions NULL is the correct thing to pass, this should be cast to the correct type if the type is not char * as other pointer types may be treated differently on different machines (eg alignment) As for assignment defined to work with 0 or NULL, this may be true but char *fred = NULL; is clearer than using 0 and only needs 3 extra key-presses so it is surely preferable. Certain machines (eg Motorola sv6350) NEED (char *)0 so NULL is shorter to type. Moral: in general, but not always, things such as NULL may be optional but were defined to avoid the programmer needing to be aware of differences in machine architecture, if you dont use them thats OK but your programs may only work on the machine on which you wrote them
jpn@teddy.UUCP (John P. Nelson) (08/24/87)
>Kernighan and Ritchie introduced NULL (one assumes) for the simple >reason that pointers are not the same as interges (nor shorts, longs etc) >If you use NULL the correct value will always be used. assume: making an ASS out of U and ME. This is wrong. Please people, we have hashed this to death. For the last time, NULL is NOT somehow special, it is simply a #define that MUST be the same as zero. This is true in both K&R and ANSI C. Anyone who believes differently is MISINFORMED. This has been discussed to death in comp.lang.c also. As for K&R, this is what K&R says about NULL (re: an example function pair, alloc and free, section 5.4). NULL is quite clearly shown as having the value 0. I quote: C guarantees that no pointer that validly points at data will contain zero, so a return value of zero can be used to signal an abnormal event, in this case, no space. We write NULL instead of zero, however, to indicate more clearly that this is a special value for a pointer. So NULL is simply a #defined constant with the value 0, and it is used instead of the contant zero to make the meaning clear. That is ALL! It has NO SPECIAL SIGNIFICANCE beyond that! Let's move this discussion to /dev/null
greg@gryphon.CTS.COM (Greg Laskin) (08/26/87)
In article <283@axis.fr> mickey@axis.fr (Michael Dance) writes: >In article <4291@teddy.UUCP>, jpn@teddy.UUCP (John P. Nelson) writes: >> >> To summarize: when passing a null pointer to a function, you should >> always cast the 0 or NULL to the proper pointer type. In any other >> context, you may use 0 or NULL interchangably. CORRECT! > >So for functions NULL is the correct thing to pass, this should be cast >to the correct type if the type is not char * as other pointer types >may be treated differently on different machines (eg alignment) WRONG! > >As for assignment defined to work with 0 or NULL, this may be true K&R: " ... it is guaranteed that assignment of the constant 0 to a pointer will produce a null pointer distiguishable from a pointer to any object." >but > char *fred = NULL; >is clearer than using 0 and only needs 3 extra key-presses so MATTER OF TASTE but agrees in general with K&R. >it is surely preferable. Certain machines (eg Motorola sv6350) >NEED (char *)0 so NULL is shorter to type. BROKEN COMPILER! > >Moral: > in general, but not always, things such as NULL may be optional > but were defined to avoid the programmer needing to be aware > of differences in machine architecture, if you dont use them > thats OK but your programs may only work on the machine on which > you wrote them Good moral. Wrong reason. K&R: "C guarantees that no pointer that validly points at data will contain zero, so a return value of zero can be used to signal an abnormal event ... We write NULL instead of zero, however, to indicate more clearly that this is a special value for a pointer. In general, integers cannot meaningfully be assigned to pointers; zero is a special case." -- Greg Laskin "When everybody's talking and nobody's listening, how can we decide?" INTERNET: greg@gryphon.CTS.COM UUCP: {hplabs!hp-sdd, sdcsvax, ihnp4}!crash!gryphon!greg UUCP: {philabs, scgvaxd}!cadovax!gryphon!gregf