wescott@ncrcae.UUCP (Mike Wescott) (03/17/85)
What's the proper conversion of a short to an unsigned int? In otherwords should the conversion be a sign extension of the short treated as an unsigned int after sign extension, or should there be no sign extension? Does K&R say anything? How about the draft C standard? What's your feeling?
ndiamond@watdaisy.UUCP (Norman Diamond) (03/19/85)
> What's the proper conversion of a short to an unsigned int? > In otherwords should the conversion be a sign extension of the > short treated as an unsigned int after sign extension, or should > there be no sign extension? (int) (unsigned) x does not necessarily equal (unsigned) (int) x -- Norman Diamond UUCP: {decvax|utzoo|ihnp4|allegra}!watmath!watdaisy!ndiamond CSNET: ndiamond%watdaisy@waterloo.csnet ARPA: ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa "Opinions are those of the keyboard, and do not reflect on me or higher-ups."
darryl@ISM780.UUCP (03/20/85)
[Stop me before I quote again!] K&R, page 184, section 6.6, "Arithmetic Conversions": "A great many operators cause conversions and yield result types in a similar way. This pattern will be called the "usual arithmetic conversions". "First, any operands of type char or short are converted to int, and any of type float are converted to double. : : : "Otherwise, if either operand is unsigned, the other is converted to unsigned and that is the type of the result. : : : The new version of the C reference manual supplied with system V changes the results in the case of long x unsigned; in K&R, this results in a long, but now it is an unsigned long (is there any real difference?). --Darryl Richman, INTERACTIVE Systems Corp. ...!cca!ima!ism780!darryl The views expressed above are my opinions only.
wescott@ncrcae.UUCP (Mike Wescott) (03/21/85)
The motivation for the original posting on this question, (which I belatedly canceled so as to make a more reasoned submission), is an inconsistency in the C-compiler concerning the conversion of short to unsigned int. Both SYsVr2 and 4.2BSD compilers exhibit the inconsistency: unsinged int ui; unsigned short us; short s; . . . s = -3; us = -3; ui = s; printf("%x %x %x\n", ui, us, s); prints fffffffd fffd fffffffd as expected. However the comparison if ((unsigned int)s == us) printf("OOPS\n"); prints OOPS meaning that fffffffd == 0000fffd !!! The code generated for the comparison is a cmpw _s, _us No conversion. K&R confused me with the "otherwise" phrase in the section on arithmetic conversions. The version of the C standard was not much more help but it eventually became clear that the code for the comparison is improperly generated. The short should be sign extend and the unsigned short should be padded with 0's on the left and the compare should be a cmpl. The piece of code that brought this to light was SysVr2's uucp code in pk0.c/chksum(), where the code register short sum; register unsigned short t; . . . if ((unsigned)sum <= t) { . . . "broke" on a new compiler. Explicitly casting to "unsigned short" fixed the checksum calculation (i.e. made uucp talk to our vax). Looking at the code generated on the vax pointed up the inconsistency. BTW, the cast (unsigned) implies (unsigned int), and the vax C-compiler produces a cmpw for both casts. Mike Wescott NCR Corp. ncrcae!wescott
ndiamond@watdaisy.UUCP (Norman Diamond) (03/22/85)
> unsinged int ui; > unsigned short us; > short s; > > s = -3; > us = -3; > ui = s; > > if ((unsigned int)s == us) printf("OOPS\n"); > > prints OOPS meaning that fffffffd == 0000fffd !!! It could mean 0000fffd == 0000fffd. If (unsigned int) s is sometimes equivalent to (unsigned int) (int) s, but other times equivalent to (unsigned int) (unsigned short) s, then I don't think any rule is being violated. A compiler does not have to be consistent in its treatment of ambiguous constructs. (In fact, inconsistency should be encouraged because it quickens the discovery of bugs.) -- Norman Diamond UUCP: {decvax|utzoo|ihnp4|allegra}!watmath!watdaisy!ndiamond CSNET: ndiamond%watdaisy@waterloo.csnet ARPA: ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa "Opinions are those of the keyboard, and do not reflect on me or higher-ups."
ken@turtlevax.UUCP (Ken Turkowski) (03/24/85)
In article <2128@ncrcae.UUCP> wescott@ncrcae.UUCP (Mike Wescott) writes: > unsigned short us; > short s; > . > . > . > s = -3; > us = -3; > ui = s; ... > > if ((unsigned int)s == us) printf("OOPS\n"); > >prints OOPS meaning that fffffffd == 0000fffd !!! >The code generated for the comparison is a > > cmpw _s, _us > >No conversion. K&R confused me with the "otherwise" phrase >in the section on arithmetic conversions. The version of the C standard >was not much more help but it eventually became clear that the code for >the comparison is improperly generated. The short should be sign extend >and the unsigned short should be padded with 0's on the left and the >compare should be a cmpl. I disagree. The "(unsigned int)" is a cast, saying that s is to be considered unsigned rather than signed. It is NOT a conversion. The fact that s was declared to be a "short int" is immaterial; it is of type int rather than float, etc. This has the same effect as saying "(unsigned)", without the "int". Int has no inherent size associated with it; the size of an int is machine-dependent. If you want an int of a specific size, you say "short int" or "long int". I would suggest that you try the statement if ((unsigned long int)s == us) printf("OOPS\n"); instead, and see if you get the same results. This explicitly specifies a size conversion. -- Ken Turkowski @ CADLINC, Menlo Park, CA UUCP: {amd,decwrl,hplabs,nsc,seismo,spar}!turtlevax!ken ARPA: turtlevax!ken@DECWRL.ARPA
ndiamond@watdaisy.UUCP (Norman Diamond) (03/27/85)
> The "(unsigned int)" is a cast, saying that s is to be > considered unsigned rather than signed. It is NOT a conversion. The > fact that s was declared to be a "short int" is immaterial; it is of > type int rather than float, etc. This has the same effect as saying > "(unsigned)", without the "int". Int has no inherent size associated > with it; the size of an int is machine-dependent. If you want an int > of a specific size, you say "short int" or "long int". > -- Ken Turkowski @ CADLINC, Menlo Park, CA A cast had better do conversion. Can you imagine (float) 3 being some epsilon-ish sort of value? Can you imagine char *c; int *x; x = (int *) c; not converting from (char *) to (int *) ? (This is irrelevant on machines that use char * for all pointers. If a machine uses byte offsets for char * ... such as calloc still is supposed to return ... and the assignment doesn't CONVERT the result of calloc to int * ... then we might as well give up with C.) -- Norman Diamond UUCP: {decvax|utzoo|ihnp4|allegra}!watmath!watdaisy!ndiamond CSNET: ndiamond%watdaisy@waterloo.csnet ARPA: ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa "Opinions are those of the keyboard, and do not reflect on me or higher-ups."
henry@utzoo.UUCP (Henry Spencer) (03/27/85)
There was a certain vagueness about the definition of casts in the V7 C reference manual; they were rather new. In particular, it wasn't clear whether they caused a conversion or just caused the compiler to think a conversion had been done. After some confusion, their semantics were clarified, and the official word from DMR (and now from the ANSI committee) is that casting to type foo is equivalent to assigning to a temporary variable of type foo. So yes, casts are conversions. -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry