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

TypeTypical sizeTypical range
char1 byte−128 to 127 (or 0 to 255)
short2 bytes−32,768 to 32,767
int4 bytesabout ±2.1 billion
long8 bytes (4 on Windows)about ±9.2 × 1018
long long8 bytesabout ±9.2 × 1018
float4 bytesabout 7 significant digits
double8 bytesabout 15–16 significant digits
long double8–16 bytesat 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:

C
#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;
}
Output
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:

C
#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;
}
Output
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.

C
#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;
}
Output
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.

Try it yourself · main.c
Edit the code, copy it into main.c, then compile and run it with cc -std=c17 -Wall main.c -o main && ./main. How to set up a C compiler
Output
10 ints take 40 bytes
long double: 8 bytes