[news.software.b] News for Xenix on PC AT ?

dantso@bach.UUCP (04/16/87)

	Sorry if this issue has been covered before....

	Has anyone ported/tried to run 2.11 news on a PC AT running Xenix ?

	Any particular problems, hints ? If the work is substantial, can it be
obtained ?

	Thanks.

dyer@spdcc.COM (Steve Dyer) (04/16/87)

I have 2.11 news, patch #8, running on my SCO XENIX system.
It came up much easier than earlier systems; the main problem
was in working around Microsoft's broken implementation of
the System V lockf() calls as non-advisory.


-- 
---
Steve Dyer
dyer@harvard.harvard.edu
dyer@spdcc.COM aka {ihnp4,harvard,linus,ima,bbn,halleys}!spdcc!dyer

dave@sds.UUCP (dave schmidt x194) (04/17/87)

In article <18346@ucbvax.BERKELEY.EDU>, dantso@bach.BERKELEY.EDU (Dan Ts'o) writes:
> 	Has anyone ported/tried to run 2.11 news on a PC AT running Xenix ?


Well, I did.  Parts of it were painful, and some parts still don't work
(in particular, if I save an article to a file, news dumps core).  Big
problems to watch out for:

1: mail is in /usr/bin rather than /bin where everything expects it to be.
   some programs ignore the MAILER #define, so you have to fgrep the
   source for it.

2: news makes huge stack demands.  Compile w/ the -F switch and a value of 4000
   or so.

3: the cc command can only handle a small number of -D directives, so you
   have to make a header file containing the ten zillion -D flags.  Then,
   either modify localize.sh (boo...) to do this for you, or "correct"
   the Makefile so that whenever you change the Makefile, make doesn't re-make
   your Makefile, thereby destroying your changes.  (I hated that...)

4: stupid problems from [censored] programmers who think that
   sizeof(int) == sizeof(char *) is a universal constant.  similiar
   problems from similar programmers who assign pointers of different
   types w/o casts. (e.g.  char * = char ** w/ no cast).  also present
   are things like:
	charptr = malloc(1024);
	if ( !charptr ) ...	/* this should be (charptr != (char *)NULL) */


5: none of the standard ways to get your system node id work under Xenix.

6: i never got patch 8 to work.


If that makes it sound initimidating, take heart -- it really wasn't
that bad, and I did get it running in a couple of days.  Good luck!


Dave Schmidt

guy%gorodish@Sun.COM (Guy Harris) (04/20/87)

>4: stupid problems from [censored] programmers who think that
>   sizeof(int) == sizeof(char *) is a universal constant.  similiar
>   problems from similar programmers who assign pointers of different
>   types w/o casts. (e.g.  char * = char ** w/ no cast).  also present
>   are things like:
>	charptr = malloc(1024);
>	if ( !charptr ) ...	/* this should be (charptr != (char *)NULL) */

This last one falls under the heading of "stupid problems from
[censored] compiler writers who didn't understand C before inflicting
something that they claim is a C compiler on Xenix users."

	if (!charptr) ...

is IDENTICAL in meaning to

	if (charptr == 0) ...

which, in turn, is IDENTICAL in meaning to

	if (charptr == (char *)0) ...

if "charptr" is of type "char *".

dave@sds.UUCP (dave schmidt x194) (04/22/87)

In article <17005@sun.uucp>, guy%gorodish@Sun.COM (Guy Harris) writes:
> >   [... commentary on problems w/ news s/w ...]  also present
> >   are things like:
> >	charptr = malloc(1024);
> >	if ( !charptr ) ...	/* this should be (charptr != (char *)NULL) */
> 
> This last one falls under the heading of "stupid problems from
> [censored] compiler writers who didn't understand C before inflicting
> something that they claim is a C compiler on Xenix users."
> 
> 	if (!charptr) ...
> 
> is IDENTICAL in meaning to
> 
> 	if (charptr == 0) ...
> 
> which, in turn, is IDENTICAL in meaning to
> 
> 	if (charptr == (char *)0) ...
> 
> if "charptr" is of type "char *".


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.

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)".  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)	*/
	...

Given my #define for NULL, statements of this kind make the compiler
complain (as it should).  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.


Dave Schmidt

(A firm believer in defensive programming.)

jss@hector.UUCP (04/23/87)

In article <146@sds.UUCP> dave@sds.UUCP writes:
>
>Why is "if (charptr == 0)" NOT identical to "if ((int)charptr == 0)" ???

Because the language definition says it isn't.  The relevant paragraphs
of K&R and ANSI proposal (I don't have H&S at hand)

K&R: 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 ...

ANSI: An integral constand expression with the value 0, or such an
expression cast to type void *, is called a null pointer constant. If
a null pointer constant is assigned to or compared for equality to a
pointer, the constant is converted to a pointer of that type ...

Jerry Schwarz

gwyn@brl-smoke.UUCP (04/23/87)

In article <146@sds.UUCP> dave@sds.UUCP (dave schmidt x194) writes:
-In article <17005@sun.uucp>, guy%gorodish@Sun.COM (Guy Harris) writes:
-> >   [... commentary on problems w/ news s/w ...]  also present
-> >   are things like:
-> >	charptr = malloc(1024);
-> >	if ( !charptr ) ...	/* this should be (charptr != (char *)NULL) */
-> 
-> This last one falls under the heading of "stupid problems from
-> [censored] compiler writers who didn't understand C before inflicting
-> something that they claim is a C compiler on Xenix users."
-> 
-> 	if (!charptr) ...
-> 
-> is IDENTICAL in meaning to
-> 
-> 	if (charptr == 0) ...
-> 
-> which, in turn, is IDENTICAL in meaning to
-> 
-> 	if (charptr == (char *)0) ...
-> 
-> if "charptr" is of type "char *".
-
-
-Why is "if (charptr == 0)" NOT identical to "if ((int)charptr == 0)" ???

Because that's not what the C language specification says happens for such
a comparison.

-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.

No cast is needed for the 0; 0 has special pointer properties in addition
to its use as an integer constant.

-  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.

Another person has made the mistake of contradicting Guy in an area he is
expert in.  Guy's explanation is EXACTLY RIGHT independent of machine
architecture or implementation, including bit pattern used to represent a
null pointer (always written as 0 at the C source level regardless of the
implementation).

He, I, and others have explained more than once before in the C newsgroup
that the only fully correct definition of the macro NULL, as C now stands,
is as 0.  (Under the proposed ANSI standard you could probably get away
with defining it as (void *)0.)

I will agree that writing
	if ( !pointer )
is bad style, but it is nonetheless technically correct.  If your compiler
can't handle this, then it is broken; perhaps you should try to get it fixed.

guy@gorodish.UUCP (04/23/87)

> 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.

blarson@castor.usc.edu.UUCP (04/24/87)

In article <146@sds.UUCP> dave@sds.UUCP (dave schmidt x194) writes:
>In article <17005@sun.uucp>, guy%gorodish@Sun.COM (Guy Harris) writes:
>Why is "if (charptr == 0)" NOT identical to "if ((int)charptr == 0)" ???

Because it is identical to if(charptr == (char *)0) by the specifications
of the C language.  (K&R, H&S, and ANSI all agree on this.)
They differ because
>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.  
And a good concientions compiler writer would write a compiler that compiles
the langue in question, not something vaugly resembling it.

>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.

Such architecutal oddities MUST be covered by the compiler/runtime system.
A cast from an int to a pointer NEEDS to convert 0 to the approprate
unusable pointer.  Redefining NULL does not redefine C.  A compiler that
does not handle this is not a C compiler.

>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.  

Writing code to avoid everything that is broken in some compiler is impossible.
Why bother trying?

>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)".

No, NULL should be defined as 0.  Comparisons and assignments to ANY pointer
type then work correctly, by definition.  Remember, "if(intptr == NULL)" should
work too, and "int *" and "char *" are NOT the same type.

>Unfortunately for me, XENIX correctly defines
>NULL, leaving me to deal with statements such as:

You mean uncorrectly.

[example deleted]

>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.

Yes, there are some broken stdio.h's out there, and NULL should be used only
as a pointer value.

>Dave Schmidt
>
>(A firm believer in defensive programming.)

You avoid the bugs in your compiler, I'll avoid the bugs in mine.  Don't
expect me to agree that the language has been redefined by a broken compiler.
-- 
Bob Larson
Arpa: Blarson@Usc-Eclb.Arpa
Uucp: (several backbone sites)!sdcrdcf!usc-oberon!castor.usc.edu!blarson
			seismo!cit-vax!usc-oberon!castor.usc.edu!blarson

greg@utcsri.UUCP (04/24/87)

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...

dave@sds.UUCP (dave schmidt x194) (04/24/87)

In article <2440@ulysses.homer.nj.att.com>, jss@hector..UUCP (Jerry Schwarz) writes:
> In article <146@sds.UUCP> dave@sds.UUCP writes:
> >
> >Why is "if (charptr == 0)" NOT identical to "if ((int)charptr == 0)" ???
> 
> Because the language definition says it isn't.  The relevant paragraphs
> of K&R and ANSI proposal (I don't have H&S at hand)
> 
> K&R: 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 ...

OK, so the language provides that 0 has magical properties; even without
this statement from K&R, I would expect the correct cast to made.  However,
as a matter of style, I personally prefer to explicitly cast the 0 to
type char *.  This, I admit, comes from working with brain-damaged compilers
that don't always the correct conversion; some recent C compilers for the
PC family don't properly compare 32-bit pointers to 16-bit int's.  Only
the low 16-bits are checked, so you can get bit if you don't do the
cast yourself.  At this point, many of you would say "It's a compiler
problem, not my problem".  Well, if that's the only C compiler you have
at your disposal, it is your problem.  (I personally would not fork out a
couple of hundred bucks just to avoid doing a cast here and there.)
Hopefully, the company will soon
correct the problem and issue a fix in the next release.  However, would
you go to a client a say : "I'm going to be a month late for the deadline
because the compiler is brain-damanged"?  The fact of the matter is that
language specification or no, some compilers do not produce code to
conform to the specification.  Since you could be unlucky enough to 
get inflicted with one, it's a matter of good style & defensive programming
to protect yourself from such problems.

But what about K&R saying "A pointer to which 0 has been assigned is
guaranteed not to point to any object..."?  I think an exception exists
to this within the standard UNIX C library. Signal() returns a pointer
to a function; in the event of an error, -1 is returned, not 0.  As far
as I know, all other functions that return a pointer, return 0 on error.
This seems to imply that 0 may be a valid function address; not being
familiar with UNIX internals, I can't say for certain, but other O/S's
load programs such that they regard their starting address as 0.
Anyway, if function f() has starting address 0, and I cast f's address
to char *, that pointer points to something, no?
On the other hand, if 0 cannot be a valid function address, why does
signal not return 0 on error?  I would be curious to know.

Dave Schmidt

john@viper.UUCP (John Stanley) (04/24/87)

In article <5787@brl-smoke.ARPA> 
gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
 >
 >He, I, and others have explained more than once before in the C newsgroup
 >that the only fully correct definition of the macro NULL, as C now stands,
 >is as 0.  (Under the proposed ANSI standard you could probably get away
 >with defining it as (void *)0.)
 >

Actualy, you -must- use (void *)0 -OR- 0 and be consistant one way or
the other.  It's not an option...  If I had to choose, I'd say use

	#define NULL	((void*)0)

because it's used as a pointer in 98% of the code I've seen and for
the following reason...

This isn't important on machines where sizeof(pointer) == sizeof(int),
but if you're using (as a simple example) a machine where pointers are
32 bit and ints are 16 bits then code containing the following function
may have problems if you change how NULL is defined:

	char *myfunc(ind, str, ind2)
	int ind, ind2;
	char *str;
	{
	char mystr[80];

	if (str == NULL)
		str = mystr;


	 ...... some code .....


	return (str);
	}

now, later in my program if I have NULL defined as 0, then the following
line will cause the wrong number of bytes to be pushed on the stack:

	myfunc( i1, NULL, i2 );

If you use NULL as a pointer, it -must- always actualy be a pointer or
your code will break any time you try to pass it as a constant to a 
function.

You may claim, if you wish, that passing NULL as a constant is illegal,
but I've seen too many examples of code where it's been done to accept
that as a valid argument.  If there already exists a large body of code
using a particular construct, then that construct may be "illegal" in
your opinion, but anyone discussing "the only fully correct definition"
must take it into account...

--- 
John Stanley (john@viper.UUCP)
Software Consultant - DynaSoft Systems
UUCP: ...{amdahl,ihnp4,rutgers}!{meccts,dayton}!viper!john

john@viper.UUCP (John Stanley) (04/24/87)

In article <17245@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
 >> Why is "if (charptr == 0)" NOT identical to "if ((int)charptr == 0)" ???
 >
 >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.
 >

 Correct, but more importantly, casting the pointer to an int will
truncate the pointer to whatever the number of bits an int would
have on that system.  This means, on a machine with 16 bit int's and
32 bit pointers, that any pointer which lies on a 64k boundry would
test as equal to NULL which is obviously -w.r.o.n.g-.

 >
 >  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.  

  Wrong...  Ever hear of something called "NULL"?

K&R, Page 97:
  "We write NULL instead of zero, however, to indicate clearly that
this is a special value for a pointer."...

 >> (!charptr) isn't portable
 >
 >Yes, it is.

Although you may find one or two compilers which balk at this
construct, it is correct on all "architectures".  The compiler
writers just need to fix their implementations on this one...

--- 
John Stanley (john@viper.UUCP)
Software Consultant - DynaSoft Systems
UUCP: ...{amdahl,ihnp4,rutgers}!{meccts,dayton}!viper!john

dan@prairie.UUCP (Daniel M. Frank) (04/25/87)

In article <2440@ulysses.homer.nj.att.com> jss@hector (Jerry Schwarz) writes:
>K&R: 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 ...

   Oh.  The VAX compiler and linker appear to arrange that (char *)0
ALWAYS points to a null string.  Other systems do the same (I believe
HP/UX does, given the unportability of code in a popular user-friendly
mail agent published on the this network).  If the VAX would have the
decency to fault on null pointer dereferencing, a lot of code written
on it would be a heck of a lot more portable.

-- 
      Dan Frank (w9nk)
	ARPA: dan@db.wisc.edu			ATT: (608) 255-0002 (home)
	UUCP: ... uwvax!prairie!dan		     (608) 262-4196 (office)
	SNAILMAIL: 1802 Keyes Ave. Madison, WI 53711-2006

dan@prairie.UUCP (Daniel M. Frank) (04/25/87)

In article <5787@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>He, I, and others have explained more than once before in the C newsgroup
>that the only fully correct definition of the macro NULL, as C now stands,
>is as 0.  (Under the proposed ANSI standard you could probably get away
>with defining it as (void *)0.)

   No.  On the 8086 family, in large model, if NULL is defined as 0, then
such things as 

	execl(..., NULL) ;

will fail, because a pointer (32-bit) parameter is expected, and an int
(16-bit) parameter is passed, with some garbage in the stack making up the
difference.  Lint will not catch this, either, because execl is /*VARARGS*/.

   It's pretty safe to define NULL as 0L when in large model, but the best
solution of all is (void *)0, or type-specific NULLs (i.e. NULLCHAR).
The (void *)0 solution may cause problems with lint, though.

-- 
      Dan Frank (w9nk)
	ARPA: dan@db.wisc.edu			ATT: (608) 255-0002 (home)
	UUCP: ... uwvax!prairie!dan		     (608) 262-4196 (office)
	SNAILMAIL: 1802 Keyes Ave. Madison, WI 53711-2006

wcs@ho95e.ATT.COM (Bill.Stewart) (04/25/87)

In article <5787@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
:In article <146@sds.UUCP> dave@sds.UUCP (dave schmidt x194) writes:
:-In article <17005@sun.uucp>, guy%gorodish@Sun.COM (Guy Harris) writes:
:-> This last one falls under the heading of "stupid problems from
:-> [censored] compiler writers who didn't understand C before inflicting
:-> something that they claim is a C compiler on Xenix users."
:[  ... much discussion by everyone about differences between
:-> 	if (!charptr) ...		/* Ugly but correct, says Doug	*/
:-> 	if (charptr == 0) ...		/* Best 			*/
:-> 	if (charptr == (char *)0) ...	/* Almost always ok		*/
:-      if ((int)charptr == 0)		/* WRONG, of course		*/
:]
:He, I, and others have explained more than once before in the C newsgroup
:that the only fully correct definition of the macro NULL, as C now stands,
:is as 0.  (Under the proposed ANSI standard you could probably get away
:with defining it as (void *)0.)

Be careful saying this: it's only correct when you're using NULL in
	if (charptr == NULL)
But (as Guy periodically has to remind VAX-users), you can't
simply use NULL in constructs like:
	foo( arg1, arg2, NULL, arg4);
because subroutine foo() might be expecting an argument of a different
size.  If you #define NULL 0, then you pass foo sizeof(int) bytes;
if you #define NULL (void *)0, then you pass it sizeof(void *) bytes.
If you're passing NULL (or other non-int constants), always cast to
	foo( arg1, arg2, (whatever_type) NULL, arg4);
	so the routine receives what you passed.
-- 
# Bill Stewart, AT&T Bell Labs 2G-202, Holmdel NJ 1-201-949-0705 ihnp4!ho95c!wcs

gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/26/87)

In article <148@sds.UUCP> dave@sds.UUCP (dave schmidt x194) writes:
>... some recent C compilers for the
>PC family don't properly compare 32-bit pointers to 16-bit int's.  Only
>the low 16-bits are checked ...

There is no such thing as a "proper" way to do this!  The compiler may do
anything, including terminating compilation with a fatal error.  Why are
you trying to do such a thing in the first place?

>But what about K&R saying "A pointer to which 0 has been assigned is
>guaranteed not to point to any object..."?

This is meant to guarantee that the address of any object will not match
a 0 pointer, so that 0 can have the reserved special meaning of a null
pointer without problems arising.  For a straightforward implementation
of C on a nice regular architecture, this means that address 0 in the
process address space must not be assigned to any visible object by the
linker.  For UNIX systems, this is done by reserving storage at that
address within the run-time startoff header module that is linked at the
beginning of user processes.  The linker could also be kludged up to
start psect assignments at I or D address 1, 2, or whatever.

>On the other hand, if 0 cannot be a valid function address, why does
>signal not return 0 on error?

This is an artifact from the good old days when PDP-11 UNIX was the only
relevant C implementation.  Integer 0 == pointer 0 was used for SIG_DFL
and value 1 was used for SIG_IGN; being a system call, the common error
return module "cerror" was used, and it always returned integer -1.  The
"integer equivalents" 0, 1, and -1 for what are properly (void (*)())
cannot be guaranteed to be meaningful on all architectures, which is why
you should use the macros SIG_DFL, SIG_IGN, and SIG_ERR instead.  (Some
systems don't yet define SIG_ERR, but X3J11 and IEEE 1003.1 require it.)

gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/26/87)

In article <888@viper.UUCP> john@viper.UUCP (John Stanley) writes:
>	myfunc( i1, NULL, i2 );
>
>If you use NULL as a pointer, it -must- always actualy be a pointer or
>your code will break any time you try to pass it as a constant to a 
>function.

No matter what NULL is defined as, the above usage is non-portable and
will break on some systems.  The problem is that the widths of pointers
of various types are in general different (and different from an (int)),
so that the wrong parameter alignment will occur unless one happens to
be lucky.  If you pass NULL as a function parameter, you should always
cast it to the correct pointer type, as in
	myfunc( i1, (struct foo *)NULL, i2 );

It is certainly true that there is a lot of code that makes this
mistake; I must have fixed several hundred occurrences of this
particular bug by now.  That does not make it any less erroneous.

For implementations of the draft proposed American National Standard
for C, if a function prototype happens to be in scope, the compiler is
required to automatically convert the parameters to have types that
match the prototype.  That would let you get away with such sloppy
coding practice without ever realizing what is happening, which is why
some of us are opposed to automatic parameter type coercion.

henry@utzoo.UUCP (Henry Spencer) (04/27/87)

>    No.  On the 8086 family, in large model, if NULL is defined as 0, then
> such things as 
> 
> 	execl(..., NULL) ;
> 
> will fail, because a pointer (32-bit) parameter is expected...

Quite true, because the code is incorrect.  The correct way to write this,
obsolete manuals notwithstanding, is:

	execl(..., (char *)NULL);

>    It's pretty safe to define NULL as 0L when in large model, but the best
> solution of all is (void *)0...

In correct, portable pre-X3J11 C, THERE IS NO WAY TO AVOID THE char * CAST!
The problem is that pointers of different types are not even guaranteed
to have the same size, much less the same representation, so there is
no, repeat *NO*, "generic NULL pointer".  This doesn't matter much except
at the function-call interface, since the compiler will get it right
elsewhere if NULL is just 0 (and if the compiler is compiling C, not
some peculiar variant of it)... but at the function-call interface it
matters very much and there is simply no substitute for typing a few
extra characters to get it right!

It is popular to botch this.  That does not make it right.
-- 
"If you want PL/I, you know       Henry Spencer @ U of Toronto Zoology
where to find it." -- DMR         {allegra,ihnp4,decvax,pyramid}!utzoo!henry

goudreau@dg_rtp.UUCP (Bob Goudreau) (04/27/87)

In article <889@viper.UUCP> john@viper.UUCP (John Stanley) writes:
>In article <17245@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
> >
> >  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.  
>
>  Wrong...  Ever hear of something called "NULL"?
>
>K&R, Page 97:
>  "We write NULL instead of zero, however, to indicate clearly that
>this is a special value for a pointer."...

Sorry, but Guy is correct.
NULL isn't a feature of C anymore than EOF, stdin or stdout are;
these are just literals defined in stdio.h.
The preprocessor converts these references to the appropriate constants,
so the compiler sees only the "bare bones" C.

-- 
Bob Goudreau
Data General Corp.
62 Alexander Drive
Research Triangle Park, NC  27709
(919) 248-6231
...!mcnc!rti-sel!dg_rtp!goudreau

greg@utcsri.UUCP (04/27/87)

In article <889@viper.UUCP> john@viper.UUCP (John Stanley) writes:
> >  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.  
>
>  Wrong...  Ever hear of something called "NULL"?
>
>K&R, Page 97:
>  "We write NULL instead of zero, however, to indicate clearly that
>this is a special value for a pointer."...

But NULL is #defined as 0, so this is nothing but a commenting device in
K & R C.
The two classic examples where it fails to work are:

	func_expecting_char_ptr(NULL);

func(0) causes an *int* to be pushed.

	char_ptr = a<b? NULL: NULL;

The RHS of the assignment is not a constant with type int and value 0,
so the above is not legal ( as opposed to "a<b? char_ptr:0 ", in which
the 0 is converted to a null char * by virtue of it being across the :
from one ).

Both of these can be fixed by the up-and-coming semantics of void* (NULL being
defined as ((void*)0) ), and function prototypes won't hurt.
-- 
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg
Have vAX, will hack...

mike@turing.unm.edu (Mike Bushnell) (04/27/87)

In article <148@sds.UUCP> dave@sds.UUCP (dave schmidt x194) writes:
>...
>On the other hand, if 0 cannot be a valid function address, why does
>signal not return 0 on error?  I would be curious to know.
>
>Dave Schmidt

Because *every* function in section 2 of the manual returns -1 on an error.
It just happens that signal is one of the very few which normally return
pointers.  If compiler writers were *really* nasty, they could make this
bomb.  Fortunately, they are on our side.  I like to cast signal to an int
before checking for -1 just to be on the safe side.

					Michael I. Bushnell
					a/k/a Bach II
					hi!turing!mike@hc.dspo.gov

guy@gorodish.UUCP (04/27/87)

>Signal() returns a pointer to a function; in the event of an error, -1 is
>returned, not 0.  As far as I know, all other functions that return a
>pointer, return 0 on error.  This seems to imply that 0 may be a valid
>function address;

No, you're inferring (incorrectly) that 0 may be a valid function address.

>not being familiar with UNIX internals, I can't say for certain, but other
>O/S's load programs such that they regard their starting address as 0.

As UNIX is a portable operating system, it is not meaningful to ask
whether UNIX loads programs such that they regard their starting
address as 0.  Some implementations do, some don't.  (Ours doesn't.)

However, just because a UNIX implementation loads a program such that
it regards its starting address as 0 does NOT mean that the address
of any function known to C within that program is necessarily 0.  In
fact, a C implementation is obliged to do whatever is necessary to
ensure that no function in a program will have the address 0; a
"nop" or a "br .+N" at location 0 should be sufficient.

>On the other hand, if 0 cannot be a valid function address, why does
>signal not return 0 on error?  I would be curious to know.

Because:

	1) other system calls return -1 on error (including a System
	V shared memory call that returns a pointer);

	2) the special signal value for "this signal is not caught"
	is usually a null pointer, so a call to "signal" that is
	successful can return a null pointer.

guy@gorodish.UUCP (04/27/87)

> >He, I, and others have explained more than once before in the C newsgroup
> >that the only fully correct definition of the macro NULL, as C now stands,
> >is as 0.  (Under the proposed ANSI standard you could probably get away
> >with defining it as (void *)0.)
> >
>
>Actualy, you -must- use (void *)0 -OR- 0 and be consistant one way or
>the other.  It's not an option...

Why?

>	char *myfunc(ind, str, ind2)
>	int ind, ind2;
>	char *str;

	...

>>now, later in my program if I have NULL defined as 0, then the following
>line will cause the wrong number of bytes to be pushed on the stack:
>
>	myfunc( i1, NULL, i2 );

1) Your program will *also* have problems if you define NULL as
"(void *)0", if "(char *)0" and "(void *)0" don't have the same
representation.

2) Your program *won't* have problems if you defined "myfunc" as

	char *
	myfunc(int ind, char *str, int ind2)

	...

because the compiler would perform the coercion of 0 into (char *)0.

>You may claim, if you wish, that passing NULL as a constant is illegal,
>but I've seen too many examples of code where it's been done to accept
>that as a valid argument.  If there already exists a large body of code
>using a particular construct, then that construct may be "illegal" in
>your opinion, but anyone discussing "the only fully correct definition"
>must take it into account...

No, they don't.  Calling "myfunc(i1, NULL, i2)" is illegal if NULL is
defined as 0, and "lint" will tell you that.  No implementor is
obliged to make this illegal construct work.

guy@gorodish.UUCP (04/27/87)

> >  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.  
>
>  Wrong...  Ever hear of something called "NULL"?

Wrong... Ever hear of something called a "preprocessor"?  NULL is
*not* a token defined by the language's grammar.  It's a preprocessor
definition, so it ultimately has to expand to *something*, and the
only thing it can expand to is "0".

guy@gorodish.UUCP (04/27/87)

>Be careful saying this: it's only correct when you're using NULL in
>	if (charptr == NULL)

Or if you're declaring and defining functions with prototype
arguments, which the ANSI C standard (which Doug referred to) permits
and recommends.  If you use prototype arguments, the compiler will
convert 0 or (void *)0 to the proper type.

guy@gorodish.UUCP (04/27/87)

>   No.  On the 8086 family, in large model, if NULL is defined as 0, then
>such things as 
>
>	execl(..., NULL) ;
>
>will fail,

So?  That call is illegal.  Yes, I know "lint" won't catch it, but
"lint" won't catch attempts to dereference null pointers, either.

>   It's pretty safe to define NULL as 0L when in large model, but the best
>solution of all is (void *)0, or type-specific NULLs (i.e. NULLCHAR).
>The (void *)0 solution may cause problems with lint, though.

The best solution of all is properly casting NULL when passing it as
an argument.

dyer@spdcc.COM (Steve Dyer) (04/28/87)

Goodness knows there are enough things to complain about with the 286 chip
and the XENIX 286 C compiler and libraries that attempt to use it, especially
when you try to use the 286 large and huge memory models.

However, the use of the (very common) constructs:
char *charp;
if (!charp) 
or
if (charp == NULL)
is NOT one of them; they work fine.

Having wrestled now with SCO XENIX for more than a year, bereft of sources,
I suspect the the original poster had a fit of paranoia; after trying to get
anything to run on this machine, you begin doubting your tools, your choice
of memory models, and finally your own understanding of the C language
itself!  Be kind... :-)

News 2.11 patchlevel 8 runs just fine on SCO XENIX.  Interested parties can
get it from my machine:
spdcc Any ACU {1200,2400,300} 16176614927 login: uucp

uucp spdcc!~uucp/compress compress	(12-bit compress)
uucp spdcc!~uucp/sconews.tar.Z .
ln compress uncompress
uncompress sconews.tar

I haven't turned this into a set of diffs between standard 2.11 patch 8
and this distribution, mainly because I haven't had the time.  The only
XENIX-specific changes are in the System V locking code which needed to be
changed to use XENIX locking, because as implemented under SCO XENIX,
System V locking is enforced against ALL processes, and not just those
which use the lockf system calls.  This means that locking the ACTIVE
file (as during expire) loses.  This is clearly wrong according to the
SVID and all other System V implementations, but they passed the SVID
test, so therefore it's OK (or so they say...)  There's a file called
XENIXCHANGES in the src subdirectory which explains what I did.
-- 
Steve Dyer
dyer@harvard.harvard.edu
dyer@spdcc.COM aka {ihnp4,harvard,linus,ima,bbn,halleys}!spdcc!dyer

henry@utzoo.UUCP (Henry Spencer) (04/28/87)

> Both of these can be fixed by the up-and-coming semantics of void* (NULL being
> defined as ((void*)0) ), and function prototypes won't hurt.

Not quite correct:  "void *" does ***NOT*** fix the func(NULL) problem,
although function prototypes do, if consistently applied.  (They have other
problems, and I'm not sure they were a good idea, but they do solve this
particular hassle after a fashion.)
-- 
"If you want PL/I, you know       Henry Spencer @ U of Toronto Zoology
where to find it." -- DMR         {allegra,ihnp4,decvax,pyramid}!utzoo!henry

allbery@ncoast.UUCP (04/29/87)

As quoted from <5787@brl-smoke.ARPA> by gwyn@brl-smoke.ARPA (Doug Gwyn ):
+---------------
| I will agree that writing
| 	if ( !pointer )
| is bad style, but it is nonetheless technically correct.  If your compiler
| can't handle this, then it is broken; perhaps you should try to get it fixed.
+---------------

HAH!!!

The System V.2 pcc is the first version that gets this correct consistently;
in fact, it's the first version that gets "if (!x)" for any x which may not
necessarily be constrained to values in the set {0, 1} correct.  (You would
not believe the problems I've had bringing up phantasia under Xenix 2.3 and
3.0 for Tandy 6000 and under System III for Plexus, due to this.)  As a
result, whether it's ``technically correct'' or not I refuse to use that
feature in my own programs, in the interests of allowing people using old pcc's
to compile my programs.

I don't know what the heck pcc was doing before (or what it's doing now; I
wouldn't trust it as far as I could throw it) but we aren't the only ones
that use it.  I just pray daily for Plexus to release V.3 with the Green
Hills compiler.

++Brando
-- 
Brandon S. Allbery	{decvax,cbatt,cbosgd}!cwruecmp!ncoast!allbery
Tridelta Industries	{ames,mit-eddie,talcott}!necntc!ncoast!allbery
7350 Corporate Blvd.	necntc!ncoast!allbery@harvard.HARVARD.EDU
Mentor, OH 44060	+01 216 255 1080

m5d@bobkat.UUCP (04/29/87)

In article <148@sds.UUCP> dave@sds.UUCP (dave schmidt x194) writes:
>       . . .  This, I admit, comes from working with brain-damaged compilers
>that don't always the correct conversion; some recent C compilers for the
>PC family don't properly compare 32-bit pointers to 16-bit int's.  Only
>the low 16-bits are checked, so you can get bit if you don't do the
>cast yourself.  At this point, many of you would say "It's a compiler
>problem, not my problem".  . . .
>
>Dave Schmidt

Well, at this point I would say that you're confused if you think that
comparison between int and pointer variables is defined at all.  The
only "integer" value defined to be usable in pointer comparisons is
zero.  It is NOT OK to compare an integer variable directly to a pointer.
It is ok to cast the int explicitly to a pointer and then compare, but
I don't know what this means on an iAPX 86-based compiler.  I don't
know what it would use for a segment value; probably zero, but
it might use the current DS.  In any case you'd probably want a
library function to construct a pointer from two integers (or a long
I guess).


-- 
Mike McNally, mercifully employed at Digital Lynx ---
    Where Plano Road the Mighty Flood of Forest Lane doth meet,
    And Garland fair, whose perfumed air flows soft about my feet...
uucp: {texsun,killer,infotel}!pollux!bobkat!m5d (214) 238-7474

allbery@ncoast.UUCP (05/01/87)

As quoted from <442@prairie.UUCP> by dan@prairie.UUCP (Daniel M. Frank):
+---------------
| In article <2440@ulysses.homer.nj.att.com> jss@hector (Jerry Schwarz) writes:
| >K&R: 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 ...
| 
|    Oh.  The VAX compiler and linker appear to arrange that (char *)0
| ALWAYS points to a null string.  Other systems do the same (I believe
| HP/UX does, given the unportability of code in a popular user-friendly
| mail agent published on the this network).  If the VAX would have the
+---------------

Huh???  Our computer's linker (Plexus P/60, System V; Plexus P/35, System
III on ncoast also) starts data segment allocatioon at address 2, so pointers
to 0 and 1 are guaranteed to cause core dumps; Elm came up fine on both
(barring the fact that someone installed it on ncoast by copying elm to
/usr/local/bin instead of running "make install"...)

++Brando
-- 
Copyright (C) 1987 Brandon S. Allbery -- you can redistribute only if your
	recipients can.

Brandon S. Allbery	{decvax,cbatt,cbosgd}!cwruecmp!ncoast!allbery
Tridelta Industries	{ames,mit-eddie,talcott}!necntc!ncoast!allbery
7350 Corporate Blvd.	necntc!ncoast!allbery@harvard.HARVARD.EDU
Mentor, OH 44060	+01 216 255 1080

allbery@ncoast.UUCP (05/01/87)

As quoted from <17436@sun.uucp> by guy%gorodish@Sun.COM (Guy Harris):
+---------------
| >>now, later in my program if I have NULL defined as 0, then the following
| >line will cause the wrong number of bytes to be pushed on the stack:
| >
| >	myfunc( i1, NULL, i2 );
| 
| 1) Your program will *also* have problems if you define NULL as
| "(void *)0", if "(char *)0" and "(void *)0" don't have the same
| representation.
+---------------

Pardon me???!  (void *) is a GENERIC pointer, is it not?  It should, in
theory, be a type pun in all situations (if casting the result of a rational
malloc() (defined as returning (void *)) changes the representation of the
pointer returned, we've got trouble, no?).

+---------------
| 2) Your program *won't* have problems if you defined "myfunc" as
| 
| 	char *
| 	myfunc(int ind, char *str, int ind2)
+---------------

If you have an X3J11 compiler, let me know; *mine* takes (void *) and proceeds
to ignore the argument/variable from that point on (no error on the type, but
the variable is not defined).  Which compiler?  Which machine?

++Brando
-- 
Copyright (C) 1987 Brandon S. Allbery -- you can redistribute only if your
	recipients can.

Brandon S. Allbery	{decvax,cbatt,cbosgd}!cwruecmp!ncoast!allbery
Tridelta Industries	{ames,mit-eddie,talcott}!necntc!ncoast!allbery
7350 Corporate Blvd.	necntc!ncoast!allbery@harvard.HARVARD.EDU
Mentor, OH 44060	+01 216 255 1080

guy%gorodish@Sun.COM (Guy Harris) (05/03/87)

> Pardon me???!  (void *) is a GENERIC pointer, is it not?

If a pointer of type "void *" is a generic C pointer, it is also a
square circle, a method for trisecting an angle with compass and
straightedge, and an expansion of "pi" to the last decimal place.
None of the objects described exist.

A pointer of type "void *" is just a pointer that can receive the
properly-coerced value of any pointer; said coercion must be
reversable.  From the October 1, 1986 ANSI C draft:

	3.2.2.3 Pointers

	   A pointer to "void" may be converted to a pointer to an
	object of any type.  A pointer to an object of any type may
	be convetrted to a pointer to "void" and back again; the
	result shall compare equal to the original pointer.

> It should, in theory, be a type pun in all situations

I can't quite parse this.  A type pun is an action, not an object, so
a pointer of type "void *" cannot be a type pun.

> (if casting the result of a rational malloc() (defined as returning
> (void *)) changes the representation of the pointer returned, we've got
> trouble, no?).

No.  Why should it cause any trouble?

> If you have an X3J11 compiler, let me know;

The person in question referred, in passing, to "void *" in such a
way that I inferred that the context of the discussion was of X3J11
compilers.

jimp@cognos.uucp (Jim Patterson) (05/05/87)

(Sorry, I missed the original posting)

>As quoted from <442@prairie.UUCP> by dan@prairie.UUCP (Daniel M. Frank):
>| The VAX compiler and linker appear to arrange that (char *)0
>| ALWAYS points to a null string.

This can't be the VAX/VMS C compiler. On our system page 0
(addresses 0 to 511.) is always reserved, not for any special
hardware considerations but so references to a NULL pointer will
fail ungraciously.  (This is considered to be a program error that
should be corrected).  This is true of NULL character pointers as well.
-- 
Jim Patterson
Cognos Inc.

dan@prairie.UUCP (05/08/87)

In article <655@cognos.UUCP> jimp@cognos.UUCP (Jim Patterson) writes:
>>As quoted from <442@prairie.UUCP> by dan@prairie.UUCP (Daniel M. Frank):
>>| The VAX compiler and linker appear to arrange that (char *)0
>>| ALWAYS points to a null string.
>
>This can't be the VAX/VMS C compiler. 

   Ok.  I meant the VAX BSD Unix compiler.  My apologies for ignoring a
large segment (no pun intended) of the VAX-using public.

   By the way, there is a linker option in SVR2 that forces a 0-value
pointer to point to a null string.  It's only available in small model
on the 286 (for obvious reasons), but I wonder how much it's used by
VAX System V programmers.

-- 
      Dan Frank (w9nk)
	ARPA: dan@db.wisc.edu			ATT: (608) 255-0002 (home)
	UUCP: ... uwvax!prairie!dan		     (608) 262-4196 (office)
	SNAILMAIL: 1802 Keyes Ave. Madison, WI 53711-2006

tim@ism780c.UUCP (Tim Smith) (05/09/87)

In article <17439@sun.uucp> guy@sun.UUCP (Guy Harris) writes:
< Or if you're declaring and defining functions with prototype
< arguments, which the ANSI C standard (which Doug referred to) permits
< and recommends. 

Are there many compilers that allow this now, or are most people
waiting for the ANSI C standard to become real?  LightspeedC on
the Mac allows it, but that is the only one I know of.
-- 
Tim Smith		"Learn to juggle while it's still legal"
sdcrdcf!ism780c!tim