[comp.lang.c] result type of assignment statements

chris@mimsy.UUCP (Chris Torek) (07/04/87)

In article <262@auvax.UUCP> rwa@auvax.UUCP (Ross Alexander) writes:
>The following discussion is all relative to
> 
> 	#define EOF -1
> 	char c;
> 	while ( ( c = getchar() ) != EOF ) { /* do something */ }
> 
>In article <22635@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
>>On a machine where "char" is not signed, this won't work.... "getchar"
>>will return EOF when it hits end-of-file; EOF (-1) will get converted
>>to '\377' ... which compares equal to 255 but not to -1.

>Isn't there a little room here for arguement?

No.  (Sorry.)

>Now of course K&R say that an expression is coerced to the type
>it is being assigned to.

As does the draft C standard.  This is pretty well set in concrete.

>... Or phrased a little differently, is the comparison being made
>to the value of c or the value of the getchar() ?

According to the C language definitions, the comparison is being
made to the value of c.

>So the coercion for the assignment of `int' to `char' in this case
>is a side effect and shouldn't have an affect on the value of the
>whole expression `( c = getchar() )'.

It does and should.

>Interestingly enough, the VAX 4.2bsd cc agrees with me,

It is buggy.  (This is a surprise? :-) )

>and produces (code to get value of getchar() ommited, but it's in r0):  
>
>		cvtlb	r0,-1(fp)	; coercion and assignment to c as byte
>		cmpl	r0,$-1		; but comparison is int to int
>		jeql	L36		; break the loop iff same

This is an incorrect optimisation.  The `officially proper' code is

	cvtlb	r0,-1(fp)
	cvtbl	-1(fp),r0
	cmpl	r0,$-1
	jeql	L36

which can be simplified to

	cvtlb	r0,-1(fp)
	cvtbl	r0,r0
	cmpl	r0,$-1
	jeql	L36

or (4.3BSD cc uses this)

	cvtbl	r0,-1(fp)
	cmpb	r0,$-1		# legal iff `char' is signed
	jeql	L36

Note, however, that the values returned by `getchar' are all in
the range -1..255.  Since `cvtbl' sign extends a byte, the only
case this misses is 255, which should compare equal, but does not.
The combination of proper source code (the coder *meant* to compare
the `char' c with the value -1) with improper object code yeilding
improper results is so rare that no one noticed it for years.

>Just to point out where the logical extension of case two gets us,
>what is the value of x in this fragment:
>
>	float x;
>	int i;
>
>	x = 2.0 + ( i = 3.5 );

It is 5.0; 4.3BSD PCC gets it right.

>I would say 5.5; others might say 5.0, it seems.  But if I _wanted_
>5.0, I would expect to write
>
>	x = 2.0 + (int) ( i = 3.5 );
>
>and I appeal to the principle of least astonishment for justification.

For better or for worse, C is defined in a way that you have found
astonishing.  If you wish to define a new language that works the
other way, that is fine, but please do not call it `C'.  (While you
are defining, you might fix some of the things *I* think are warts.
But I will not call it `C' either.)

(Incidentally, given the definition of a C cast, your final example
would be equivalent to your penultimate, were the value of an
assignment the value of the right hand side.  You would still get
5.5.  You could redefine casting, of course.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

peter@sugar.UUCP (Peter DaSilva) (07/06/87)

Make c an int. No problem. EOF is not a valid character, and you get the
benefit that you can add other out-of-band information.

	if((c = getch(ttyfd)) != EOF) {
		switch(c) {
			case FRAMING_ERROR:
			case BREAK:
			case PARITY_ERROR:
		}
	}
-- 
-- Peter da Silva `-_-' ...!seismo!soma!uhnix1!sugar!peter (I said, NO PHOTOS!)