[comp.sources.d] Something's Broken: was ... Re: tgetent

rwwetmore@grand.waterloo.edu (Ross Wetmore) (07/08/88)

In article <1033@ficc.UUCP> peter@ficc.UUCP (Peter da Silva) writes:
>In article <3222@bigtex.uucp>, james@bigtex.uucp (James Van Artsdalen) writes:
>> IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
>>>     - Don't use "0" to mean NULL ( i.e. (char *)0 ).
>> This last statement is incorrect, or rather, evidence of a broken
>> compiler.

>He's speaking in the context of a function call. Large model 286
>programs have 32 bit pointers but 16 bit integers, so if you pass
>0 to a function expecting a pointer the stack will be off by two
>bytes.

And large model '386 programs have 48 bit pointers and 32 bit ints ...

>So, the problem isn't a broken compiler, it's a broken CPU architecture.

>-- `-_-' Peter (have you hugged your wolf today) da Silva.
>--   U   Ferranti International Controls Corporation.

  The assumption that pointers and ints are of equal length is the 
problem, no? This is a fundamental assumption of the 'C' language, 
if not an explicit requirement.

  It would be unfair to fault either the architecture, or compiler in
this case. It just means the 'C' language was designed for a certain
class of hardware and thus has limited use in its pristine (unkludged) 
form.

Ross W. Wetmore                 | rwwetmore@water.NetNorth
University of Waterloo          | rwwetmore@math.Uwaterloo.ca
Waterloo, Ontario N2L 3G1       | {uunet, ubc-vision, utcsri}
(519) 885-1211 ext 3491         |   !watmath!rwwetmore

" Maynard) (07/10/88)

In article <19789@watmath.waterloo.edu> rwwetmore@math.Uwaterloo.ca (Ross Wetmore) writes:
>  The assumption that pointers and ints are of equal length is the 
>problem, no? This is a fundamental assumption of the 'C' language, 
>if not an explicit requirement.

NO!!!!!
Before I let the wizards in comp.lang.c (Doug Gwyn, Chris Torek, Karl
Heuer, and Henry Spencer come immediately to mind) shred this statement,
I'll point a flame at it:

C does NOT require that pointers and integers be interchangeable. Any
attempt to do so is inherently non-portable.
That some folks (most notably, those from the school of "All the world's
a VAX running BSD") get away with that is a crying shame, for it makes
the rest of us have innumerable problems attempting to port their code.

>  It would be unfair to fault either the architecture, or compiler in
>this case. It just means the 'C' language was designed for a certain
>class of hardware and thus has limited use in its pristine (unkludged) 
>form.

You're right; the real blame lies with the (incompetent) programmer.

Both the language and the architecture do their job just fine, thank
you.
(Note to Peter: Me, defending C??!?!!)

-- 
Jay Maynard, EMT-P, K5ZC...>splut!< | Never ascribe to malice that which can
uucp:       uunet!nuchat!           | adequately be explained by stupidity.
   hoptoad!academ!uhnix1!splut!jay  +----------------------------------------
{killer,bellcore}!tness1!           | Birthright Party '88: let's get spaced!

root@cca.ucsf.edu (Computer Center) (07/12/88)

In article <19789@watmath.waterloo.edu>, rwwetmore@grand.waterloo.edu (Ross Wetmore) writes:
> 
>   The assumption that pointers and ints are of equal length is the 
> problem, no? This is a fundamental assumption of the 'C' language, 
> if not an explicit requirement.

Please learn what you are talking about before posting. See K&R p. 210

    A pointer may be converted to any of the integral types large
    enough to hold it. Whether an int or long is required is machine
    dependent.

Thos Sumner       (thos@cca.ucsf.edu)   BITNET:  thos@ucsfcca
(The I.G.)        (...ucbvax!ucsfcgl!cca.ucsf!thos)

OS|2 -- an Operating System for puppets.

#include <disclaimer.std>

peter@ficc.UUCP (Peter da Silva) (07/12/88)

In article ... rwwetmore@grand.waterloo.edu (Ross Wetmore) writes:
> In article <1033@ficc.UUCP> peter@ficc.UUCP (Peter da Silva) writes:
> >In article ... james@bigtex.uucp (James Van Artsdalen) writes:
    [ the statement "Don't use 0 to mean NULL" is evidence of a broken
      compiler ]

> >He's speaking in the context of a function call. Large model 286
> >programs have 32 bit pointers but 16 bit integers, so if you pass
> >0 to a function expecting a pointer the stack will be off by two
> >bytes.

> And large model '386 programs have 48 bit pointers and 32 bit ints ...

Large model '386 programs? Whatever for? By the time you need that much
address space the '386 will long be history. I should hope that the 586
(or whatever you call it in that day) will have 64-bit registers.

> >So, the problem isn't a broken compiler, it's a broken CPU architecture.

>   The assumption that pointers and ints are of equal length is the 
> problem, no? This is a fundamental assumption of the 'C' language, 
> if not an explicit requirement.

No, the aspect of the '386 that's broken is the fact that the address
space is not contiguous. This is a problem with any language. I guess
I wasn't too precise about this. Anyway...

If you want to pass NULL to a function, cast it to the right pointer
type until such time as you have an ANSI conformant compiler and this
last major hole in the typing structure of the language is closed.

  [ 'C' is pretty useless in it's unkludged form ]

I really don't think you meant to imply that function prototypes are
a kludge, right?
-- 
-- `-_-' Peter (have you hugged your wolf today) da Silva.
--   U   Ferranti International Controls Corporation.
-- Phone: 713-274-5180. CI$: 70216,1076. ICBM: 29 37 N / 95 36 W.
-- UUCP: {uunet,academ!uhnix1,bellcore!tness1}!sugar!ficc!peter.

peter@ficc.UUCP (Peter da Silva) (07/12/88)

In article <1061@ficc.UUCP>, I said...
> No, the aspect of the '386 that's broken is the fact that the address
> space is not contiguous.

Of course, I meant the '286. The '386 is the first decent processor intel's
come out with since the 8085.
-- 
-- `-_-' Peter (have you hugged your wolf today) da Silva.
--   U   Ferranti International Controls Corporation.
-- Phone: 713-274-5180. CI$: 70216,1076. ICBM: 29 37 N / 95 36 W.
-- UUCP: {uunet,academ!uhnix1,bellcore!tness1}!sugar!ficc!peter.

rwwetmore@grand.waterloo.edu (Ross Wetmore) (07/12/88)

In article <1305@ucsfcca.ucsf.edu> root@cca.ucsf.edu (Computer Center) writes:
>In article <19789@watmath.waterloo.edu>, rwwetmore@grand.waterloo.edu (Ross Wetmore) writes:
>>   The assumption that pointers and ints are of equal length is the 
>> problem, no? This is a fundamental assumption of the 'C' language, 
>> if not an explicit requirement.
>Please learn what you are talking about before posting. See K&R p. 210
>    A pointer may be converted to any of the integral types large
>    enough to hold it. Whether an int or long is required is machine
>    dependent.
>Thos Sumner       (thos@cca.ucsf.edu)   BITNET:  thos@ucsfcca

  Since this obviously touches a sensitive nerve of the C purists, let
me rephrase with examples. As well, let us keep the discussion on a 
relatively Platonic plane, and avoid the religious fervor that leads
to argument by drowning the opposition with insult :-)

  (int)n = (char *)p - (char *)q;

  This is perfectly valid 'C' and will never to my knowledge be picked
up by any lint program. While 'C' goes to great lengths to tell you all
about the non-portability of many of its features (I have read the 
Bible above from cover to cover), the above statement has a fundamental
assumption that the separation of two addresses is representable by an
integer value, or if you regress one step taking into account the
warning that such expressions should only be used when p and q are
addresses within the same object, that the size of any C object cannot
exceed the number of items that can be held in an integer word.

  The related case has similar fundamental linkages between the size of
an integer word and pointers.

  (char *)p += n;

  The fact that NULL, defined as the integer constant 0, is explicitly
defined to be a valid null pointer on assignment (but not generally, 
which is what caused the original problem) only reinforces the linkage.

  C goes to great lengths to warn you about all the problems that arise 
when you make the assumption that an integer word and pointer are
interchangeable, or that pointer arithmetic must be done with integer
sized words. The bottom line is that C code must restrict itself to the 
subset of cases where the size of the address space can be represented
by an int and vice versa, or it develops a lot of non-portable extensions
(warts :-) such as the example of NULL which is valid for use in some
cases but not in others. 

  Thus the observation that pristine/portable C has a fundamental
assumption built into it about the relative sizes of pointers and ints.
Violating this assumption leads to non-portable extensions of the
language. The fact that C specifications go to great lengths not to
make this an explicit requirement, does not stop it from being a
practical fundamental assumption.

Ross W. Wetmore                 | rwwetmore@water.NetNorth
University of Waterloo          | rwwetmore@math.Uwaterloo.ca
Waterloo, Ontario N2L 3G1       | {uunet, ubc-vision, utcsri}
(519) 885-1211 ext 3491         |   !watmath!rwwetmore

alanf%smile@Sun.COM (Alan Fargusson) (07/15/88)

The original problem was a program that did not declare the return value of a
function.  In C it is assumed that the return value is int, but this is beside
the point.  The bug was that the return value was not declared, and declaring
it fixes the bug.

As for pointer and int problems, the size of a pointer relative to an int is a
problem with some compilers.  But this is not the only problem of this type.
On any machine calling lseek( fd, 0, 0 ) is wrong because the second argument
is a long.  This works on 32 bit machines, but not 16 bit machines.

In defense of Intel (how did I end up defending Intel) this is more of a
problem on the 68K if the compiler uses 16 bit integers.  On the 68K it is
possible to have a structure that is larger than 64Kb, so the address will not
fit in a 16 bit integer.  On the 80[12]86 it is not possible to have a
structure that is larger than 64K, and each structure will be contained in one
segment, so the difference between two address will fit in a 16 bit int.  I am
assuming that you are not using huge model.  If you are then 32 bit integers
are used for pointer arithmetic.
- - - - - - - - - - - - - - - - - - - - -
Alan Fargusson		Sun Microsystems
alanf@sun.com		..!sun!alanf

david@geac.UUCP (David Haynes) (07/18/88)

In article <19829@watmath.waterloo.edu: rwwetmore@grand.waterloo.edu (Ross Wetmore) writes:
:In article <1305@ucsfcca.ucsf.edu: root@cca.ucsf.edu (Computer Center) writes:
::In article <19789@watmath.waterloo.edu:, rwwetmore@grand.waterloo.edu (Ross Wetmore) writes:
:::   The assumption that pointers and ints are of equal length is the 
::: problem, no? This is a fundamental assumption of the 'C' language, 
::: if not an explicit requirement.
::Please learn what you are talking about before posting. See K&R p. 210
::    A pointer may be converted to any of the integral types large
::    enough to hold it. Whether an int or long is required is machine
::    dependent.
::Thos Sumner       (thos@cca.ucsf.edu)   BITNET:  thos@ucsfcca
:
:  Since this obviously touches a sensitive nerve of the C purists, let
:me rephrase with examples. As well, let us keep the discussion on a 
:relatively Platonic plane, and avoid the religious fervor that leads
:to argument by drowning the opposition with insult :-)
:
:  (int)n = (char *)p - (char *)q;
:
:  This is perfectly valid 'C'

	Read about casting lvalues again.
:                              and will never to my knowledge be picked
:up by any lint program.

 	My compiler on the other hand barfs at this sort of thing.

:                        While 'C' goes to great lengths to tell you all
:about the non-portability of many of its features (I have read the 
:Bible above from cover to cover), the above statement has a fundamental
:assumption that the separation of two addresses is representable by an
:integer value, or if you regress one step taking into account the
:warning that such expressions should only be used when p and q are
:addresses within the same object, that the size of any C object cannot
:exceed the number of items that can be held in an integer word.

Bullshit!

	Example:

	(short) n = (char *) p - (char *) q;

	Therefore:

		All pointers are short.
		(True for PDP-11s)

Cast what you want, but don't make it a fundamental of the language.

:  The related case has similar fundamental linkages between the size of
:an integer word and pointers.
:
:  (char *)p += n;

So, let's expand this shall we? 

	(char *p) += n;
	==> (char *p) = (char *p) + n;
	==> (char *p) = (char *p) + (char *)n; 
	==> no violation. Remember, types are cast to the most complex
	    rvalue and then back to match the lvalue.


:  The fact that NULL, defined as the integer constant 0, is explicitly
:defined to be a valid null pointer on assignment (but not generally, 
:which is what caused the original problem) only reinforces the linkage.

No, (char *) NULL is the null pointer. 0 is 0. If you don't believe
that, I bet a lot of your 68000-based code crashes for no apparent 
reason.

:  C goes to great lengths to warn you about all the problems that arise 
:when you make the assumption that an integer word and pointer are
:interchangeable, or that pointer arithmetic must be done with integer
:sized words. The bottom line is that C code must restrict itself to the 
:subset of cases where the size of the address space can be represented
:by an int and vice versa, or it develops a lot of non-portable extensions
:(warts :-) such as the example of NULL which is valid for use in some
:cases but not in others. 

So, if my ints are 32 bits and my pointers 64, I am not running K&R
C? Nonsense!

:  Thus the observation that pristine/portable C has a fundamental
:assumption built into it about the relative sizes of pointers and ints.
:Violating this assumption leads to non-portable extensions of the
:language. The fact that C specifications go to great lengths not to
:make this an explicit requirement, does not stop it from being a
:practical fundamental assumption.

Just because you can break the law, doesn't mean you are not doing
anything illegal. When talking about portable code, you had better
be planning to recognize the difference between a pointer and an
integer or you had better plan on spending late nights wondering
why your code keeps falling over. It's that simple --- K&R say a
pointer is a pointer and an integer is an integer and they may be of
different size. Live with it. 

:Ross W. Wetmore                 | rwwetmore@water.NetNorth

-david-

allbery@ncoast.UUCP (Brandon S. Allbery) (07/23/88)

As quoted from <19829@watmath.waterloo.edu> by rwwetmore@grand.waterloo.edu (Ross Wetmore):
+---------------
| In article <1305@ucsfcca.ucsf.edu> root@cca.ucsf.edu (Computer Center) writes:
| >In article <19789@watmath.waterloo.edu>, rwwetmore@grand.waterloo.edu (Ross Wetmore) writes:
| >>   The assumption that pointers and ints are of equal length is the 
| >> problem, no? This is a fundamental assumption of the 'C' language, 
| >> if not an explicit requirement.
| >Please learn what you are talking about before posting. See K&R p. 210
| >    A pointer may be converted to any of the integral types large
| >    enough to hold it. Whether an int or long is required is machine
| >    dependent.
| 
|   (int)n = (char *)p - (char *)q;
| 
|   This is perfectly valid 'C' and will never to my knowledge be picked
| up by any lint program. While 'C' goes to great lengths to tell you all
| about the non-portability of many of its features (I have read the 
| Bible above from cover to cover), the above statement has a fundamental
| assumption that the separation of two addresses is representable by an
| integer value, or if you regress one step taking into account the
+---------------

Not only have I used a lint (System V?  Can't check, I'm on ncoast, whose
lint and cc are braindamaged anyway) which complains about "illegal pointer
subtraction" when handed this, but Microsoft's cc for Xenix and 386 Unix
flatly refuses to compile a program which does this with basically the same
message.  (You can defeat it with a cast to (int) or (long), of course.)

I think ANSI defines pointer subtraction only when the pointers are known
to point to the same contiguous block of memory (i.e. within a single array).
Otherwise, pointer subtraction may not even be meaningful.  (It could cause
a SIGBUS on an architecture which stores teo arrays in totally different
memories -- not two parts of the same memory but a "nonscalar" memory.)  C
itself lets you do this -- that is why "lint" exists; C gives you enough
rope to hang yourself (but usually it's us non-Vax types who get hanged by
Vaxoid programs).

++Brandon
-- 
Brandon S. Allbery, uunet!marque!ncoast!allbery			DELPHI: ALLBERY
	    For comp.sources.misc send mail to ncoast!sources-misc