Unless the compiler can guarantee that the resulting value will not be changed, the following widening rules apply. A variable of types: signed char and short are widened (implicitly converted) to int. Similarly, unsigned char and unsigned short are widened to unsigned int. variables of type float are widened to double. When a longer integer is converted to a smaller integer, e.g. by a cast, the higher order bits are truncated and discarded.
When a positive value of a floating type is converted to an integer type, the result is the largest integer not greater than the floating number. When a negative value of floating type is converted to an integer type, the direction of rounding is undefined. Similarly, if the result will not fit within the integer type the value is undefined. When an integer value is converted to a floating type, there may be a loss of precision.
When a float is converted to a double the value is unchanged. When a double is converted to a float the nearest value is taken.
In an arithmetic expression, the following conversions apply.
If one operand is of type long double then the other is converted to long double if necessary and that is the type of the result. Otherwise, if one operand is of type double then the other is converted to double if necessary and that is the type of the result. Otherwise, if one operand is of type float then the other is converted to float if necessary and that is the type of the result. This last conversion is implementation dependent, as it may choose to convert to double instead. Otherwise, the integral widenings are applied.
An array of type is converted to pointer to type, except when used as the argument to the sizeof() operator.
No conversions are allowed to or from type void. But a pointer to void may be converted to a pointer to any type. And a pointer to any type may be converted to a pointer to void.
An integral expression with a value of 0 may be converted to any pointer type. Such a pointer is called a null pointer, and is supposed to be guaranteed to not point to any object. Any other integer value when converted to a pointer will need a cast to avoid a warning or error.
An object declared with the const type specifier cannot be used as an lvalue, i.e. it cannot be changed, even if converted (cast).
Implementations (e.g. PCs) which two or more different pointer sizes, especially when these lengths can differ for data address and function addresses, do not have conversion rules and many subtle errors can occur if care is not taken.