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 Type | Description | Range | Precision |
---|---|---|---|

char | 8-bit signed integer | -128 to +127 | Exact |

short | 16-bit signed integer | -32,768 to +32,767 | Exact |

int | 16 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,647 | Exact |

long | 32 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+18 | Exact |

long long | 64 or 128-bit signed integer | +/- 9.22337203685e+18 or +/- 1.7014118346e+38 | Exact |

unsigned char | 8-bit unsigned integer | 0 to 255 | Exact |

unsigned short | 16-bit unsigned integer | 0 to 65,535 | Exact |

unsigned int | 16 or 32-bit unsigned integer | 0 to 65,535 or 4,294,967,295 | Exact |

unsigned long | 32 or 64-bit unsigned integer | 0 to 4,294,967,295 or 1.84467440737e+19 | Exact |

unsigned long long | 64 or 128-bit unsigned integer | 0 to 1.84467440737e+19 or 3.40282366921e+38 | Exact |

float | Almost always 32-bit floating point | +/- (1.1754 x 10^{-38}
to 3.4028 x 10^{38}) | 24 bits (6-7 decimal digits) |

double | Almost always 64-bit floating point | +/- (2.2250 x 10^{-308}
to 1.7976 x 10^{308}) | 52 bits (15-16 decimal digits) |

long double | 64, 80, 96, or 128-bit floating point | +/- 3.3621 x 10^{-4932}
to 1.1897 x 10^{+4932}) | 114 bits (64 decimal digits) |

float complex | Two floats for real and imaginary parts | Same as float | Same as float |

double complex | Two doubles for real and imaginary parts | Same as double | Same as double |

long double complex | Two 128-bit floating point values | Same as long double | Same 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.

Why do the size of

`int`

and`long`

types vary from one computer to another?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.

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

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

A huge array of people's ages in years.

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

A single variable holding Avogadro's constant.

A large array holding values like Avogadro's constant.