Arithmetic and Data Types - The usual arithmetic conversions and promotions

Chapter chap4 section 12

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 typeType after promotion
unsigned charunsigned int
signed charint
unsigned short intunsigned int
short intint

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.666667
Consider 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 88
The 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().