OverIQ.com

Implicit Type Conversion in C

Last updated on July 27, 2020


C allows us to mix basic types in an expression. We have seen a glimpse of this behavior while discussing mixed mode arithmetic in chapter Arithmetic Operators in C. In such expressions, operand of one type is converted to another type. This process is known as Type Conversion.

There are two types of type conversion:

  1. Implicit type conversion.
  2. Explicit type conversion.

In this chapter, we are discussing Implicit type conversion.

Implicit type conversion #

This type of conversion is done by the compiler according to the following rules:

  1. If one operand is of type long double, then the other operand will be converted to long double and then the result of the operation will be a long double.
  2. Otherwise, If one operand is of type double then the other operand will be converted to double and the result of the operation will be a double.
  3. Otherwise, If one operand is of type float then the other operand will be converted to float and the result of the operation will be a float.
  4. Otherwise, If one operand is of type unsigned long int then the other operand will be converted to unsigned long int and the result of the operation will be an unsigned long int.
  5. Otherwise, If one operand is of type long intand the other is of type unsigned int then there are two possibilities:
    1. If long int can represent all the values of an unsigned int, the operand of type unsigned int will be converted to long int and the result will be a long int.
    2. Otherwise, If long int can't represent all the values of an unsigned int, the operand of both of the operands will be converted to unsigned long int and the result will be an unsigned long int.
  6. Otherwise, If one operand is of type long int then the other operand will be converted to long int and the result of the operation will be a long int.
  7. Otherwise, If one operand is of type unsigned int then the other operand will be converted to unsigned int and the result of the operation will be an unsigned int.
  8. Otherwise, If one operand is of type int then the other operand will be converted to int and the result of the operation will be an int.

Let's take some examples to make things clear.

Example 1:

1
2
3
4
int a = 100;
double b = 12.5;

a + b;

Here one operand is of type int and other is of type double. Therefore according to rule 3, the variable a will be converted to double and the result of the overall operation will be a double i.e 112.500000.

Example 2:

1
2
3
4
char ch = 'a';
int a = 10;

a + c;

Here according to rule 8, char will be converted to int before any operation and the result of the overall operation will an int. Since the integral value of ch is 97 (i.e ASCII value of the character 'a' ). Hence, 97 + 10 = 107.

Example 3:

1
2
3
4
char ch = 'A';
unsigned int a = 10;

a * b;

Here according to rule 7, variable ch of type char will be first converted to unsigned int i.e 65 (ASCII value of 'A' ), before addition will be carried out and the result of the overall operation will be an unsigned int. Hence, 65 + 10 = 75.

Here are some more examples:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
char ch;
short int si;
int i;
unsigned int ui;
float f;
long double ld;

i = ch + si;  // both ch and si will be converted to int before addition - rule 8
i = si + i;   // si will be converted to int before addition - rule 8
ui = i + ui;  // i will be converted to unsigned int before addition - rule 7
f = ui + f;   // ui will be converted to float before addition - rule 3
ld = f + ld;  // f will be converted to long double before addition - rule 1

All the above-mentioned rules can be simplified by assigning a rank to each type. Here is how it works.

Whenever two operands of different data types are involved in an expression, the operand of lower rank will be converted to a data type of higher rank. This process is called the promotion of type.

Note: Rule 5 is omitted from the figure for simplicity.

Type Conversion in assignment #

If types of the operand in an assignment expression is different, then the operand on the right-hand side will be converted to the type of left-hand operand according to the following rules.

  1. If the right-hand operand is of lower rank then it will be promoted to the rank of the left operand. Here is an example:

    int i = 'z';
    

    here right operand 'z' is of type char and the right-hand operand is of type int. According to the rule -lower rank operand (in this case char) will be promoted to a higher rank (in this case int). So before assignment 'z' i.e 122 (ASCII value) will be promoted to int and then assigned to i.

  2. Otherwise, if right-hand operand is of higher rank then it will be demoted to the rank of left-hand operand. For example:

    float a = 120.33;
    

    Recall that by default floating point constants are of type double. In this case, right-hand operand i.e 120.33 is of type double and the left-hand operand is of type float. Therefore before assignment operation 120.33 will be demoted to float type and then the assignment will take place.

Some consequences of type conversion in assignment are:

  1. High order bits may be lost when long int is converted to int or int to short int or int to char. Let's take an example to understand this point clearly. Suppose we have the following statement:

    unsigned char ch = 257;
    

    Here we are trying to assign 257 (int type) to a char variable. According to type conversion rule 2: if right-hand operand is of higher rank then it will be demoted to the rank of left-hand operand. But there is a problem, recall that unsigned char type can only take values from 0 to 255. Cleary, 257 is out of range for variable ch. In such cases, an appropriate value from the other side of the range is picked up and stored in ch. So eventually what gets stored in the ch variable is a smiley character having ASCII value 2.

  2. Fractional part will be truncated during conversion from floating point type (like double, float) to int type.

  3. When the double type is converted to float type digits are rounded off.

  4. When int is converted to float or float to double there is no increase in accuracy.

  5. When signed type is changed to unsigned type, the sign may be dropped.

The following example demonstrates how type conversion takes place.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<stdio.h>

int main()
{
    float f_val1 = 97.12, f_val2;
    int i_val1, i_val2;
    char ch_val1, ch_val2;

    // float is demoted to int, only 97 is assigned to i_val1
    i_val1 = f_val1;

    // int is demoted to char,
    ch_val1 = i_val1;

    // float is demoted to int, only 12 is assigned to i_val2
    i_val2 = 12.45f;

    // char is promoted to int, now
    // i_val1 contains ASCII value of character 'e' i.e 101
    i_val2 = 'e';

    /*
        double is demoted to float, since by
        default floating point constants
        are of type double
    */

    f_val2 = 12.34;

    // Print the value of i
    printf("Value of i_val1 = %d\n", i_val1);

    // Print the character corresponding to ASCII value 97
    printf("Value of ch_val1 = %c\n", ch_val1);

    // Print the ASCII value of character 'e'
    printf("Value of i_val2 = %d\n", i_val2);

    // Print f_val2 with 2 digits of precision
    printf("Value of f_val2 = %.2f\n", f_val2);

    // Signal to operating system everything works fine
    return 0;
}

Expected Output:

1
2
3
4
Value of i_val1 = 97
Value of ch_val1 = a
Value of i_val2 = 101
Value of f_val2 = 12.34