HPlogo HP C/HP-UX Reference Manual: Version A.05.55.02 > Chapter 4 Type Conversions

Arithmetic Conversions

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

In general, the goal of conversions between arithmetic types is to maintain the same magnitude within the limits of the precisions involved. A value converted from a less precise type to a more precise type and then back to the original type results in the same value.

Integral Conversions

A particular bit pattern, or representation, distinguishes each data object from all others of that type. Data type conversion can involve a change in representation.

When signed integer types are converted to unsigned types of the same length, no change in representation occurs. A short int value of -1 is converted to an unsigned short int value of 65535.

Likewise, when unsigned integer types are converted to signed types of the same length, no representational change occurs. An unsigned short int value of 65535 converted to a short int has a value of -1.

If a signed int type is converted to an unsigned type that is wider, the conversion takes (conceptually) two steps. First, the source type is converted to a signed type with the same length as the destination type. (This involves sign extension.) Second, the resulting signed type is converted to unsigned. The second step requires no change in representation.

If an unsigned integer type is converted to a signed integer type that is wider, the unsigned source type is padded with zeros on the left and increased to the size of the signed destination type.

When a long long (or long in the 64-bit data model) is converted into another integral data type that is of shorter length, truncation may occur. When a long long is converted into a double type, no overflow will occur, but there may be a loss of precision.

In general, conversions from wide integer types to narrow integer types discard high-order bits. Overflows are not detected. Conversions from narrow integer types to wide integer types pad on the left with either zeros or the sign bit of the source type as described above.

A “plain” char is treated as signed. A “plain” int bit-field is treated as signed.

Floating Conversions

When an integer value is converted to a floating type, the result is the equivalent floating-point value. If it cannot be represented exactly, the result is the nearest representable value. If the two nearest representable values are equally near, the result is the one whose least significant bit is zero.

When a long long is converted into a floating type no overflow will occur but may result in loss of precision. Converting a long long into a quad precision floating point value should be precise with no overflow.

When a floating type is converted into a long long type, the fractional part is discarded and overflow may occur.

When floating-point types are converted to integral types, the source type value must be in the representable range of the destination type or the result is undefined. The result is the whole number part of the floating-point value with the fractional part discarded as shown in the following examples:

int i;
i = 9.99;          /* i gets the value 9 */
i = -9.99;         /* i gets the value -9 */

float x1 = 1e38;   /* legal; double is converted to float */
float x2 = 1e39;   /* illegal; value is outside of range
                      for float */

long double x3 = 1.f;   /* legal; float is converted to long
                           double     */

When a long double value is converted to a double or float value, or a double value is converted to a float value, if the original value is within the range of values representable in the new type, the result is the nearest representable value (if it cannot be represented exactly). If the two nearest representable values are equally near, the result is the one whose least significant bit is zero. When a float value is converted to a double or long double value, or a double value is converted to a long double value, the value is unchanged.

Arrays, Pointers, and Functions

An expression that has function type is called a function designator. For example, a function name is a function designator. With two exceptions, a function designator with type “function returning type” is converted to an expression with type “pointer to function returning type.” The exceptions are when the function designator is the operand of sizeof (which is illegal) and when it is the operand of the unary & operator.

In most cases, when an expression with array type is used, it is automatically converted to a pointer to the first element of the array. As a result, array names and pointers are often used interchangeably in C. This automatic conversion is not performed in the following contexts: (1) when the array is the operand of sizeof or the unary &; (2) it is a character string literal initializing an array of characters; or (3) it is a wide string literal initializing an array of wide characters.

© Hewlett-Packard Development Company, L.P.