signed chars

John B. Nagle jbn at wdl1.UUCP
Wed Jun 13 14:47:38 AEST 1984


     The painful effort to make C portable continues.  It is unfortunate
that we don't have "signed char" as well as "unsigned char" syntax, so
that if you really needed unsigned or signed chars, you could say so, in which 
case the compiler should give it to you, even if it is slow.
     Some time ago (back when Ada was called DOD-1) I was promoting the idea
that ranges are really the way to go, and that this "short" and "long"
and "long long" (Algol-68) business was all wrong.  My ideal is as follows.

     Numeric variables are declared by giving a lower and upper bound for
their value.  There may be predefined types such as "int", but these are
just predefined ranges, not fundamental objects of the language.  These
definitions are independent of the machine being used.

     Overflow is an error.  Checking should be available.  Where hardware
checking is available (as on VAXen), it should always be on.  (For amusement,
build a VAX C compiler with the integer overflow check enable bit turned on
in the entry mask, and see how many standard programs blow up when compiled
with it.)  This implies that you can't do checksums, hashing, etc. with
the standard arithmetic operators.  This is OK, you just need some built-in
functions like "addmod(a,b,base)" that generate good open code when "base"
is a constant and a power of two.

     The type of a constant N is N..N;

     The type of an expression must accomodate the largest value that can
be generated by the values in that expression.  Thus,

	if X and Y have range 0..256
	then X*Y has range 0..65536
	and X*Y*Y has range 0..16777216

But if the compiler sees

	X = X*Y

it can optimize, and only do an 8-bit unsigned multiply, because the result
has to fit in 8 bits.  So you don't need multiple precision arithmetic for
all the simple expressions.  But

	X=X*X*X*X*X*X/(Y*Y*Y*Y*Y*Y)

would probably be considered illegal as an expression because the intermediate
range would exceed the machine limits.
     
     The compiler has to see the procedure definition to generate the call;
C suffers from this; we have to pass 32 bits on a M68000 every time we want
to pass a flag.  It simplifies the compilation problem, but I would rather
have the checking.  When there are lots of numeric types, though, you need
to see the definition at compile time, or you need lots of casts.

     What you get from all this is that you get the same answer on all machines,
regardless of the hardware available.  The compiler has to work harder, but
the code is a lot more portable.  Something to think about when it is time
to define ``D''.



More information about the Comp.unix.wizards mailing list