On Sat, Feb 21, 2015 at 10:51 AM, Chuck Guzis <cclist at sydex.com> wrote:
Consider a machine with a word length of 64 bits.
This machine represents
floating point numbers with a 16 bit exponent and a 48 bit mantissa (nothing
unusual so far).
So we have the length of short = int = long = 64 bits. So far so good.
However, given such a generous word length, the designers of this machine
decide not to dedicate special hardware toward handling 64 bit integers, but
have said that 48 bits should be long enough for anyone, and so treat
integer arithmetic as a subset of floating point (straightforward enough).
So not all values of a 64 bit word reflect valid integers--the exponent must
be a certain value--anything else is floating point.
Now, here's where we get into sticky territory. Since C draws no data type
distinctions between bitwise logical operations on ints and arithmetic
operations, is it possible to implement C on this machine?
Having short, int, and long types that occupy 64 bits of storage but
only effectively have 48 bits of integer value is perfectly fine, but
it does have some consequences that must be considered.
On all integer types other than unsigned char, the C standard allows
the representation of the type to contain padding bits, and the values
of the padding bits are unspecified (ISO/IEC 9899:1999 ?6.2.6.2 ?1).
The implementation is free to require that the padding bits have
certain values (for the exponent field in your example), and for
operands which don't have the required padding values to yield
unpredictable results (called "trap representations" (?6.2.6.2 ?5).
However, all operations with valid operand values (not trap
representations) have to generate valid values (not trap
representations) as output, so the shift and logical operations have
to be implemented in such a way that the padding bits of the result
are valid. In other words, if the native machine "logical or"
instruction was just a logical or of all 64 bits, or it was a logical
or of the low 48 bits but did not handle the exponent correctly, it
wouldn't be sufficient by itself to implement the C logical or
operator.
The unsigned char type can't use a representation using padding bits;
all of its storage bits have to be value bits (?6.2.6.1 ?3). Signed
chars have to occupy the same amount of storage as a "plain" char
(?6.2.5 ?5), and unsigned integer types have to occupy the same amount
of storage as the corresponding signed integer types (?6.2.5 ?6).
These rules combined with the requirements on the ranges of
corresponding unsigned and signed integer types (?6.2.6.2 ?2) result
in it not being possible for a signed character to have any padding
bits either.
C types aren't required to correspond to types natively handled by the
instruction set, so this problem can be resolved (on a machine such as
your example) by defining an 8-bit or 16-bit character type, even
though some operations on those would be less efficient than on the
64-bit type natively supported.