Data Types and sizeof
C's built-in types map closely to what the processor works with: integers of various sizes, floating-point numbers and characters. Unlike most languages, C only sets minimum sizes for them, so the sizeof operator is how you find the real size on your system.
The basic types
| Type | Typical size | Typical range |
|---|---|---|
char | 1 byte | −128 to 127 (or 0 to 255) |
short | 2 bytes | −32,768 to 32,767 |
int | 4 bytes | about ±2.1 billion |
long | 8 bytes (4 on Windows) | about ±9.2 × 1018 |
long long | 8 bytes | about ±9.2 × 1018 |
float | 4 bytes | about 7 significant digits |
double | 8 bytes | about 15–16 significant digits |
long double | 8–16 bytes | at least as precise as double |
"Typical" matters: the C standard only guarantees, for example, that an int is at least 16 bits and a long at least 32. On 64-bit Linux and macOS a long is 8 bytes, but on 64-bit Windows it's 4. When you need an exact size, use the fixed-width types from <stdint.h> (next lesson).
sizeof
sizeof gives the size of a type or variable in bytes. Its result has type size_t, an unsigned integer type printed with %zu:
#include <stdio.h> int main(void) { printf("char: %zu\n", sizeof(char)); printf("short: %zu\n", sizeof(short)); printf("int: %zu\n", sizeof(int)); printf("long: %zu\n", sizeof(long)); printf("long long: %zu\n", sizeof(long long)); printf("float: %zu\n", sizeof(float)); printf("double: %zu\n", sizeof(double)); double distance = 42.195; printf("distance: %zu\n", sizeof distance); return 0; }
char: 1 short: 2 int: 4 long: 8 long long: 8 float: 4 double: 8 distance: 8
These results come from a 64-bit macOS machine; 64-bit Linux prints the same. sizeof(char) is 1 by definition everywhere. With a variable, the parentheses are optional.
Characters are small integers
A char stores a number — the character's code, usually in ASCII. Printing with %c shows the character, %d the number:
#include <stdio.h> int main(void) { char letter = 'A'; printf("%c is code %d\n", letter, letter); printf("Next letter: %c\n", letter + 1); printf("'7' as a digit: %d\n", '7' - '0'); return 0; }
A is code 65 Next letter: B '7' as a digit: 7
Subtracting '0' from a digit character gives its numeric value — a common trick, since the digits '0'–'9' have consecutive codes.
Integers vs. floating point
Integer types hold exact whole numbers. Floating-point types (float, double) hold fractions, but only approximately (lesson 9). Use double by default for fractional values; float saves memory but loses precision quickly.
#include <stdio.h> int main(void) { int whole = 7 / 2; double exact = 7.0 / 2; printf("7 / 2 as int: %d\n", whole); printf("7.0 / 2 as double: %f\n", exact); return 0; }
7 / 2 as int: 3 7.0 / 2 as double: 3.500000
Dividing two integers gives an integer: the fractional part is thrown away. Make at least one operand a floating-point value to get a fractional result.
void
void means "no type": a function that returns nothing is declared void, and int main(void) means main takes no arguments. You'll also meet void *, a pointer to "anything", in lesson 36.
Try it yourself
Print the size of an array of 10 ints and of a long double on your machine. The output below is from an Apple silicon Mac; on most x86-64 Linux PCs a long double is 16 bytes.
10 ints take 40 bytes long double: 8 bytes