The binary arithmetic operations are only defined when applied to two values of the same type. If the evaluation of an expression involves values of different types various conversions are applied to one (or both) of the values to give two values of the same type. These are known as the usual arithmetic conversions . The following description is taken straight from the ANSI C standard.
First, if either operand has type long double , the other operand is converted to long double .
Otherwise, if either operand has type double , the other operand is converted to double .
Otherwise, if either operand has type float , the other operand is converted to type float .
Otherwise, the integral promotions are first applied to both operands and then the following rules are applied.
If either operand has type unsigned long int, the other operand is converted to unsigned long int.
Otherwise, if one operand has type long int and the other has type unsigned int, if a long int can represent all values of an unsigned int, the operand of type unsigned int is converted to long int; if a long int cannot represent all the values of an unsigned int, both operands are converted to unssigned long int
Otherwise, if either operand has type long int, the other operand is converted to long int.
Otherwise, if either operand has type unsigned int, the other operand is converted to unsigned int.
Otherwise, both operands have type int.
The integral promotions specify the conversion of char and short int data types to int data types in arithmetic contexts. Functional promotions specify type conversion of functional parameters. The following table shows the integral promotions
| Original type | Type after promotion |
|---|---|
| unsigned char | unsigned int |
| signed char | int |
| unsigned short int | unsigned int |
| short int | int |
The type of a promoted char depends on whether the char data type is signed or unsigned. Integral promotions are applied in the context of evaluation or arithmetic expressions. The functional promotion rules are the same as the integral promotion rules with the extra rule that float data types are converted to double
A good rule is to avoid mixing data types, especially the signed and unsigned varieties when the rules get particularly complex. However there are some occasions when normal practice expects the use of mixed data types. Consider the following program which demonstrates the mixture of integral and floating-point types in evaluating an expression, here constants of the various types are mixed but similar effects would be seen using variables.
main()
{
double x,y;
x = 1 + 2 / 3;
y = 1 + 2 / 3.0;
printf("x = %5lf, y = %5lf\n",x,y);
}
producing the output x = 1.000000, y = 1.666667Consider the expressions on the right hand side of the two assignments.
In the assignment to x the first step in evaluation of the expression is the evaluation of
2/3 Both operands are integers. Since "/" has higher precedence than "+" and there are no type conversions, the rules of integer division apply yielding the result 0 (as an integer). The addition operator then has two integral operands so yields an integral result (1) which is converted to floating point on assignment.
The second assignment proceeds rather differently. Again the first step is the evaluation of the expression
2/3.0 only in this case one of the operands is floating point so the other is converted to floating point and the rules of floating point arithmetic apply yielding the result 0.666666... The addition now has one floating point operand so the other is converted to floating point and the result assigned without conversion.
A final example of arithmetic involving objects of different types, in this case integers and characters is shown below. The program reads in a two digit number reverses the digits and displays both the number and its reversed form. The program would fail if it were not supplied with a two digit number.
main()
{
int n1=0,n2;
char c1,c2;
printf("Enter a two digit number ");
scanf("%c%c",&c1,&c2);
n1 = (c1-'0')*10 + c2-'0';
n2 = (c2-'0')*10 + c1-'0';
printf("The number was %d\n",n1);
printf("The number reversed was %d\n",n2);
printf("The sum was %d\n",n1+n2);
}
A typical dialogue is Enter a two digit number 17 The number was 17 The number reversed was 71 The sum was 88The interesting point here concerns the expressions
c1-'0' and c2-'0' The effect of evaluating these expressions is to subtract the internal representation of the character 0 (zero) from whatever was actually read in. If the internal representation of the digits 0-9 is continuous, as it would be if your computer used the ASCII character set, then this technique provides a handy way of converting from external character form to internal binary form, however it is often better to use a library function such as atoi().