On Tue, 6 Dec 2005 11:17:17 -0800 in comp.arch.embedded, "Scott
Kelley" <scottk@iccom.com> wrote:
I haven't been able to find anything in my books about math functions using
combinations of variable types. Examples:
long = long / int
long = 8000000 / int
int = 8000000 / int
unsigned char = int
I have had problems more than once with this - what sometimes seems to me
that it should work often doesn't. Is it at all compiler dependent? Where
can I find good information on the subject?
The C standard does spell this all out. Whether your compiler
complies (especially if it targets a small, e.g, 8-bit, procesor) is
another matter. If the standard is to abstruse, Harbison and Steele's
"C: A Reference Manual" is excellent. Look for "The Usual
Conversions."
Summary:
1) Integer types have rank. Each signed in type has the same rank as
the corresponding unsigned type (as well as plain char). long long
outranks long outranks int outranks short outranks char outranks _Bool
1) There are no integer expressions narrower than int. If both
operands are integer types of lower rank than int, they are converted
to int before the operator is applied, unless int cannot represent all
possible resulting values, in which case they are converted to
unsigned int.
3) Before an operator is applied, the following conversions are
applied if the operands differ in type:
if one operand is long double
convert other to long double
else if one operand is double
convert other operand to double
else if one operand is float
convert other operand to float
else if both operands are unsigned
convert lower rank operand to type of upper rank
else if both operands are signed
convert lower rank operand to type of upper rank
else if unsigned operand has >= rank of signed
convert signed operand to type of unsigned
else if signed operand cannot represent all values
of the unsigned operand
convert both to unsigned type of signed operand
3) When converting to a wider type with the same "signedness," the
value is preserved.
4) When converting from a signed integer type with negative value to
an unsigned integer type, use the unsigned value of the sign-extended
two's complement representation of the negativevalue (the words in the
standard are different, but the effect is the same). E.g., 8-bit
signed -1 to 16-bit unsigned short is 0xFF -> 0xFFFF -> 65535. E.g.2,
16-bit signed value 767 to 8-bit unsigned char is 0x2FF -> 0xFF -> 255
5) If converting to a signed integer type that can't represent the
value, the result is undefined.
For your specific examples, the results depend on the types. Assuming
a minimum system (8-bit char, 16-bit short/int, 32-bit long):
long = long / int
convert int to long, perform division
long = 8000000 / int
type of literal 8000000 is long
convert int to long, perform division
int = 8000000 / int
convert int to long, perform division, convert result to int
unsigned char = int
convert int to unsigned char.
One possible surprise is rule 2. Consider:
unsigned char x = 128, y = 32;
int z;
z = x*y;
should result in z being assigned the value 4096 rather than 0.
HTH,
-=Dave
--
Change is inevitable, progress is not.