[comp.sys.ibm.pc] ** Re: MSC 4.0 Large Model ** Original Posters problem solved!!!

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