Standard C Types

C supports the data types available in most CPUs, as well as some extended types. Table 17.1, “C Data Types” outlines the standard data types available in C.

Table 17.1. C Data Types

C TypeDescriptionRangePrecision
char8-bit signed integer-128 to +127Exact
short16-bit signed integer-32,768 to +32,767Exact
int16 or 32-bit signed integer (usually 16 bits on 8 or 16-bit processors, 32-bits on 32 or 64-bit processors)-32,768 to +32,767 or -2,147,483,648 to +2,147,483,647Exact
long32 or 64-bit signed integer (usually 32 bits on 16-bit and 32-bit processors, 64 bits on 64-bit processors)-2,147,483,648 to +2,147,483,647 or +/- 9.22337203685e+18Exact
long long64 or 128-bit signed integer+/- 9.22337203685e+18 or +/- 1.7014118346e+38Exact
unsigned char8-bit unsigned integer0 to 255Exact
unsigned short16-bit unsigned integer0 to 65,535Exact
unsigned int16 or 32-bit unsigned integer0 to 65,535 or 4,294,967,295Exact
unsigned long32 or 64-bit unsigned integer0 to 4,294,967,295 or 1.84467440737e+19Exact
unsigned long long64 or 128-bit unsigned integer0 to 1.84467440737e+19 or 3.40282366921e+38Exact
floatAlmost always 32-bit floating point+/- (1.1754 x 10-38 to 3.4028 x 1038)24 bits (6-7 decimal digits)
doubleAlmost always 64-bit floating point+/- (2.2250 x 10-308 to 1.7976 x 10308)52 bits (15-16 decimal digits)
long double64, 80, 96, or 128-bit floating point+/- 3.3621 x 10-4932 to 1.1897 x 10+4932)114 bits (64 decimal digits)
float complexTwo floats for real and imaginary partsSame as floatSame as float
double complexTwo doubles for real and imaginary partsSame as doubleSame as double
long double complexTwo 128-bit floating point valuesSame as long doubleSame as long double

C's int, long, and long long types vary in size from one platform to another. Because of this, we have to make pessimistic assumptions about the range of these types in order to write portable code. We must assume that an int has the range of a 16-bit integer and the memory requirements of a 32-bit integer, because it will on some systems. NEVER ASSUME THAT YOUR CODE WILL ONLY BE USED ON THE CPU AND OPERATING SYSTEM WHERE YOU WROTE IT. Likewise, we have to assume a long has the range of a 32-bit integer and the memory requirements of a 64-bit integer.

On 16-bit processors, int is typically 16 bits, while long is 32 bits, requiring multiple precision arithmetic. On 32-bit machines, both int and long are typically 32 bits. On 64-bit machines, int is usually 32 bits while long is usually 64 bits.

To summarize, an int could be either 16 or 32 bits, depending on where your code is compiled. A long could be wither 32 or 64 bits, depending where your code is compiled. Use int or long only if either possible size is acceptable in terms of range and memory use.

The size of int and long vary across CPUs for the sake of speed. The int type never requires multiple precision arithmetic, except perhaps on very small 8-bit microcontrollers, where an int may be 16 bits. Hence, if you want to maximize speed, and 16 bits provides enough range, and 32 bits isn't too much memory to use, then use int. Likewise, if 32 bits provides enough range, and 64 bits isn't too much memory to use, then use long.

If you need signed integers larger than +32,767 or an unsigned integer larger than 65,535, then int or unsigned int will not be big enough on 16-bit systems. Use at least a long. Always consider using unsigned before going to a larger data type. If you need values up to 50,000, but do not need negative values, then unsigned int will suffice and you do not need long, which uses more memory and may require multiple machine instructions to process.

If you want to ensure a specific size for an integer variable regardless of whether it means using multiple precision arithmetic, there are additional types defined in inttypes.h, such as int64_t and uint64_t.

#include <inttypes.h>
        
int     main(int argc, char*argv[])

{
    int32_t     myint;
    
    ...
    return 0;
}
        

If you don't need numbers larger than +32,767 and you want to limit the size of the variable to 2 bytes, then use short. This is typically only done on embedded systems with very little memory or when using very large arrays on a typical computer. Note that short values will be promoted to int in many situations, which will slow down the program.

Logical/Boolean values in C do not have a separate data type. Instead, C treats them as they are handled internally, as integers. A value of 0 represents false, and any non-zero value represents true. The standard header file stdbool.h defines a data type called bool and constants true and false. You can use these instead of integer variables and values to make programs that use Boolean variables more self-documenting.

For real numbers, use double unless saving memory is an issue. There is no significant difference in speed between float and double on modern CPUs, and double has much higher precision. Only use float for very large arrays to reduce memory use.

Practice

Note

Be sure to thoroughly review the instructions in Section 2, “Practice Problem Instructions” before doing the practice problems below.
  1. Why do the size of int and long types vary from one computer to another?

  2. What would be the best C data type to use for each of the following values? Explain your reasoning in each case. Use the C types table in the text and the adjoining explanations to make optimal choices.

    1. A single variable containing a person's age, in years.

    2. A single variable holding the temperature of a star, up to 40,000 Kelvin. The value is only approximate within 1,000 degrees.

    3. A huge array of people's ages in years.

    4. The balance of Joe Sixpack's checking account, in pennies.

    5. A single variable holding Avogadro's constant.

    6. A large array holding values like Avogadro's constant.