2.2. Integer TypesThere are five signed integer types . Most of these types can be designated by several synonyms, which are listed in Table 2-1.
For each of the five signed integer types in Table 2-1, there is also a corresponding unsigned type that occupies the same amount of memory, with the same alignment: in other words, if the compiler aligns signed int objects on even-numbered byte addresses, then unsigned int objects are also aligned on even addresses. These unsigned types are listed in Table 2-2.
C99 introduced the unsigned integer type _Bool to represent Boolean truth values. The Boolean value true is coded as 1, and false is coded as 0. If you include the header file stdbool.h in a program, you can also use the identifiers bool, TRue, and false, which are familiar to C++ programmers. The macro bool is a synonym for the type _Bool, and true and false are symbolic constants equal to 1 and 0. The type char is also one of the standard integer types. However, the one-word type name char is synonymous either with signed char or with unsigned char, depending on the compiler. Because this choice is left up to the implementation, char, signed char, and unsigned char are formally three different types.
You can do arithmetic with character variables. It's up to you to decide whether your program interprets the number in a char variable as a character code or as something else. For example, the following short program treats the char value in ch as both an integer and a character, but at different times: char ch = 'A'; // A variable with type char. printf("The character %c has the character code %d.\n", ch, ch); for ( ; ch <= 'Z'; ++ch ) printf("%2c", ch); In the printf( ) statement, ch is first treated as a character that gets displayed, and then as numeric code value of the character. Likewise, the for loop treats ch as an integer in the instruction ++ch, and as a character in the printf( ) function call. On systems that use the 7-bit ASCII code, or an extension of it, the code produces the following output: The character A has the character code 65. A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A value of type char always occupies one bytein other words, sizeof(char) always yields 1and a byte is at least eight bits wide. Every character in the basic character set can be represented in a char object as a positive value. C defines only the minimum storage sizes of the other standard types: the size of type short is at least two bytes, long at least four bytes, and long long at least eight bytes. Furthermore, although the integer types may be larger than their minimum sizes, the sizes implemented must be in the order:
The type int is the integer type best adapted to the target system's architecture, with the size and bit format of a CPU register. The internal representation of integer types is binary. Signed types may be represented in binary as sign and magnitude, as a one's complement , or as a two's complement . The most common representation is the two's complement. The non-negative values of a signed type are within the value range of the corresponding unsigned type, and the binary representation of a non-negative value is the same in both the signed and unsigned types. Table 2-3 shows the different interpretations of bit patterns as signed and unsigned integer types.
Table 2-4 lists the sizes and value ranges of the standard integer types.
In the following example, each of the int variables iIndex and iLimit occupies four bytes on a 32-bit computer: int iIndex, // Define two int variables and iLimit = 1000; // initialize the second one. To obtain the exact size of a type or a variable, use the sizeof operator. The expressions sizeof(type) and sizeof expression yield the storage size of the object or type in bytes. If the operand is an expression, the size is that of the expression's type. In the previous example, the value of sizeof(int) would be the same as sizeof(iIndex): namely, 4. The parentheses around the expression iIndex can be omitted. You can find the value ranges of the integer types for your C compiler in the header file limits.h , which defines macros such as INT_MIN, INT_MAX, UINT_MAX, and so on (see Chapter 15). The program in Example 2-1 uses these macros to display the minimum and maximum values for the types char and int. Example 2-1. Value ranges of the types char and int// limits.c: Display the value ranges of char and int. // --------------------------------------------------- #include <stdio.h> #include <limits.h> // Contains the macros CHAR_MIN, INT_MIN, etc. int main( ) { printf("Storage sizes and value ranges of the types char and int\n\n"); printf("The type char is %s.\n\n", CHAR_MIN < 0 ? "signed" :"unsigned"); printf(" Type Size (in bytes) Minimum Maximum\n" "---------------------------------------------------\n"); printf(" char %8d %20d %15d\n", sizeof(char), CHAR_MIN, CHAR_MAX ); printf(" int %8d %20d %15d\n", sizeof(int), INT_MIN, INT_MAX ); return 0; } In arithmetic operations with integers , overflows can occur. An overflow happens when the result of an operation is no longer within the range of values that the type being used can represent. In arithmetic with unsigned integer types, overflows are ignored. In mathematical terms, that means that the effective result of an unsigned integer operation is equal to the remainder of a division by UTYPE_MAX + 1, where UTYPE_MAX is the unsigned type's maximum representable value. For example, the following addition causes the variable to overflow: unsigned int ui = UINT_MAX; ui += 2; // Result: 1 C specifies this behavior only for the unsigned integer types. For all other types, the result of an overflow is undefined. For example, the overflow may be ignored, or it may raise a signal that aborts the program if it is not caught. 2.2.1. Integer Types with Exact Width (C99)The width of an integer type is defined as the number of bits used to represent a value, including the sign bit. Typical widths are 8, 16, 32, and 64 bits. For example, the type int is at least 16 bits wide. In C99, the header file stdint.h defines integer types to fulfill the need for known widths. These types are listed in Table 2-5. Those types whose names begin with u are unsigned. C99 implementations are not required to provide the types marked as "optional" in the table.
For example, int_least64_t and uint_least64_t are integer types with a width of at least 64 bits. If an optional signed type (without the prefix u) is defined, then the corresponding unsigned type (with the initial u) is required, and vice versa. The following example defines and initializes an array whose elements have the type int_fast32_t: #define ARR_SIZE 100 int_fast32_t arr[ARR_SIZE]; // Define an array arr // with elements of type int_fast32_t for ( int i = 0; i < ARR_SIZE; ++i ) arr[i] = (int_fast32_t)i; // Initialize each element The types listed in Table 2-4 are usually defined as synonyms for existing standard types. For example, the stdint.h file supplied with one C compiler contains the line: typedef signed char int_fast8_t; This declaration simply defines the new type int_fast8_t (the fastest 8-bit signed integer type) as being equivalent with signed char. Furthermore, an implementation may also define extended integer types such as int24_t or uint_least128_t. The signed intN_t types have a special feature: they must use the two's complement binary representation. As a result, their minimum value is -2N-1, and their maximum value is 2N-1 - 1. The value ranges of the types defined in stdint.h are also easy to obtain: macros for the greatest and least representable values are defined in the same header file. The names of the macros are the uppercased type names, with the suffix _t (for type) replaced by _MAX or _MIN (see Chapter 15). For example, the following definition initializes the variable i64 with its smallest possible value: int_least64_t i64 = INT_LEAST64_MIN; The header file inttypes.h includes the header file stdint.h, and provides other features such as extended integer type specifiers for use in printf( ) and scanf( ) function calls (see Chapter 15). ![]() |