The type of a variable determines how much space it occupies in storage and how the bit pattern stored is interpreted. Similarly, the type of a function determines how its return value is to be interpreted.
Types can be either predefined or derived. The predefined types in C are the basic types and the type void. The basic types consist of the integer types and the floating types.
There are five signed integer types: signed char, short int (or short), int, long int (or long), and long long int(*) (or long long(*)). For each of these types there is a corresponding unsigned integer type with the same storage size. The unsigned type is designated by the prefix unsigned in the type specifier, as in unsigned int.
The types char, signed char, and unsigned char are formally different. Depending on the compiler settings, however, char is equivalent either to signed char or to unsigned char. The prefix signed has no meaning for the types short, int, long, and long long(*), however, since they are always considered to be signed. Thus short and signed short specify the same type.
The storage size of the integer types is not defined; however, their width is ranked in the following order: char <= short <= int <= long <= long long(*). Furthermore, the size of type short is at least 2 bytes, long at least 4 bytes, and long long at least 8 bytes. Their value ranges for a given implementation are found in the header file limits.h.
ANSI C99 also introduces the type _Bool to represent Boolean values. The Boolean value true is represented by 1 and false by 0. If the header file stdbool.h has been included, then bool can be used as a synonym for _Bool and the macros true and false for the integer constants 1 and 0. Table 1-3 shows the standard integer types together with some typical value ranges.
ANSI C99 introduced the header file stdint.h(*), which defines integer types with specific widths (see Table 1-4). The width N of an integer type is the number of bits used to represent values of that type, including the sign bit. (Generally, N = 8, 16, 32, or 64.)
For example, int16_t is an integer type that is exactly 16 bits wide, and int_fast32_t is the fastest integer type that is 32 or more bits wide. These types must be defined for the widths N = 8, 16, 32, and 64. Other widths, such as int24_t, are optional. For example:
int16_t val = -10; // integer variable
// width: exactly 16 bits
For each of the signed types described above, there is also an unsigned type with the prefix u. uintmax_t, for example, represents the implementation's widest unsigned integer type.
Three types are defined to represent non-integer real numbers: float, double, and long double. These three types are called the real floating types .
The storage size and the internal representation of these types are not specified in the C standard, and may vary from one compiler to another. Most compilers follow the IEEE 754-1985 standard for binary floating-point arithmetic, however. Table 1-5 is also based on the IEEE representation.
The header file float.h defines symbolic constants that describe all aspects of the given representation (see Section 1.17).
The representation of a floating-point number x is always composed of a sign s, a mantissa m, and an exponent exp to base 2:
x = s * m * 2exp, where 1.0 <= m < 2 or m = 0
The precision of a floating type is determined by the number of bits used to store the mantissa. The value range is determined by the number of bits used for the exponent.
Figure 1-2 shows the storage format for the float type (32-bit) in IEEE representation.
The sign bit S has the value 1 for negative numbers and 0 for other numbers. Because in binary the first bit of the mantissa is always 1, it is not represented. The exponent is stored with a bias added, which is 127 for the float type.
For example, the number -2.5 = -1 * 1.25 * 21 is stored as:
S = 1, Exponent = 1+127 = 128, Mantissa = 0.25
ANSI C99 introduces special floating types to represent the complex numbers and the pure imaginary numbers. Every complex number z can be represented in Cartesian coordinates as follows:
z = x + i*y
where x and y are real numbers and i is the imaginary unit .
The real numbers x and y represent respectively the real part and the imaginary part of z.
Complex numbers can also be represented in polar coordinates:
z = r * (cos(theta) + i * sin(theta))
The angle theta is called the argument and the number r is the magnitude or absolute value of z.
In C, a complex number is represented as a pair of real and imaginary parts, each of which has type float, double, or long double. The corresponding complex floating types arefloat _Complex, double _Complex, and long double _Complex.
In addition, the pure imaginary numbers—i. e., the complex numbers z = i*y where y is a real number—can also be represented by the types float _Imaginary, double _Imaginary, and long double _Imaginary.
Together, the real and the complex floating types make up the floating types.
The type specifier void indicates that no value is available. It is used in three kinds of situations:
There are two uses for void expressions. First, functions that do not return a value are declared as void. For example:
void exit (int status);
Second, the cast construction (void)expression can be used to explicitly discard the value of an expression. For example:
(void)printf("An example.");
Prototypes of functions that have no parameters
For example:
int rand(void);
Pointers to void
The type void * (pronounced "pointer to void") represents the address of an object, but not the object's type. Such "typeless" pointers are mainly used in functions that can be called with pointers to different types as parameters. For example:
void *memcpy(void *dest, void *source, size_t count);