Q: How should I decide which integer type to use?
A: If you might need large values (above 32,767 or below -32,767), use long. Otherwise, if space is very important (i.e. if there are large arrays or many structures), use short. Otherwise, use int. If well-defined overflow characteristics are important and negative values are not, or if you want to steer clear of sign-extension problems when manipulating bits or bytes, use one of the corresponding unsigned types. (Beware when mixing signed and unsigned values in expressions, though; see question 3.19.)
Although character types (especially unsigned char) can be used as ``tiny'' integers, doing so is sometimes more trouble than it's worth. The compiler will have to emit extra code to convert between char and int (making the executable larger), and unexpected sign extension can be troublesome. (Using unsigned char can help; see question 12.1 for a related problem.)
A similar space/time tradeoff applies when deciding between float and double. (Many compilers still convert all float values to double during expression evaluation.) None of the above rules apply if pointers to the variable must have a particular type.
Variables referring to certain kinds of data, such as sizes of objects in memory, can and should use predefined abstract types such as size_t.
It's often incorrectly assumed that C's types are defined to have certain, exact sizes. In fact, what's guaranteed is that:
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)holds. [footnote]
From these values, it can be inferred that char is at least 8 bits, short int and int are at least 16 bits, and long int is at least 32 bits. (The signed and unsigned versions of each type are guaranteed to have the same size.) Under ANSI C, the maximum and minimum values for a particular machine can be found in the header file <limits.h>; here is a summary:
|Base type||Minimum size (bits)||Minimum value (signed)||Maximum value (signed)||Maximum value (unsigned)|
If for some reason you need to declare something with an exact size (usually the only good reason for doing so is when attempting to conform to some externally-imposed storage layout, but see question 20.5), be sure to encapsulate the choice behind an appropriate typedef, but see question 1.3.
If you need to manipulate huge values, larger than the guaranteed range of C's built-in types, you need an arbitrary-precision (or ``multiple precision'') arithmetic library; see question 18.15d.
K&R1 Sec. 2.2 p. 34
K&R2 Sec. 2.2 p. 36, Sec. A4.2 pp. 195-6, Sec. B11 p. 257
ISO Sec. 22.214.171.124.1, Sec. 126.96.36.199
H&S Secs. 5.1,5.2 pp. 110-114