Skip to content

Beginner · Getting started with C · topic 4 of 60 · 30 min

Data types and their sizes

Explanation

C has char, short, int, long and long long for whole numbers (signed or unsigned), and float and double for decimals. Their sizes depend on the platform: on typical 64-bit Linux, int is 4 bytes and long is 8, but on 64-bit Windows long is 4. Use sizeof to check, limits.h for ranges, and stdint.h types like int32_t when you need an exact size. Uninitialised local variables hold garbage.

Why sizes matter in C

In C, every type occupies a fixed number of bytes, and that number limits the values it can hold. Unlike Java, C does not fix most sizes; the standard only gives minimums, and the compiler chooses for each platform. Code that assumes long is 8 bytes works on Linux and silently breaks on Windows. sizeof tells you the size in bytes for the machine you compile on.

c
#include <stdio.h>

int main(void) {
    printf("char      %zu\n", sizeof(char));       // always 1
    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));
    printf("pointer   %zu\n", sizeof(void *));
    return 0;
}
%zu is the format for sizeof results (type size_t).
Type64-bit Linux/macOS (LP64)64-bit Windows (LLP64)Typical range (4-byte int)
char11-128..127 or 0..255 (signedness varies!)
short22-32,768..32,767
int44-2,147,483,648..2,147,483,647
long84depends on platform
long long88about ±9.2 × 10^18
float / double4 / 84 / 8~7 / ~15 significant digits
pointer88(addresses)

signed and unsigned

Integer types are signed by default (they hold negatives). unsigned versions hold only zero and positives, with double the positive range: unsigned int goes from 0 to 4,294,967,295 on these platforms. Whether plain char is signed or unsigned depends on the platform, so use signed char or unsigned char when it matters (for bytes, use unsigned char).

Ranges from limits.h, exact sizes from stdint.h

c
#include <limits.h>
#include <stdint.h>
#include <inttypes.h>

printf("%d %d\n", INT_MIN, INT_MAX);        // -2147483648 2147483647 (with a 4-byte int)
int32_t  balance = -500;                    // exactly 32 bits, signed
uint8_t  pin_state = 1;                     // exactly 8 bits, unsigned (0..255)
uint64_t file_size = 5000000000ULL;         // exactly 64 bits
printf("%" PRIu64 "\n", file_size);         // portable printf format for uint64_t

Use int for everyday counting, size_t for sizes and array indexes (it is what sizeof and strlen return), and fixed-width types from stdint.h for file formats, network protocols and hardware registers (module 12), where the exact number of bits matters.

Constants and literals

c
const double GST_RATE = 18.0;   /* a read-only variable */
#define MAX_STUDENTS 60          /* a preprocessor constant (module 8) */
10      /* int */      10U   /* unsigned int */   10L  /* long */   10LL /* long long */
3.14    /* double */   3.14f /* float */
'A'     /* a character constant, value 65 in ASCII */
0x1F    /* hexadecimal 31 */      017 /* OCTAL 15: a leading 0 means octal! */

Declaring and initialising

c
int count;          /* declared but NOT initialised: holds garbage if local */
int total = 0;      /* declared and initialised */
printf("%d\n", count);   /* undefined behaviour: may print any number */
Careful: Local variables in C are not set to zero automatically. Reading one before assigning it is undefined behaviour and a classic source of "works on my machine" bugs. Initialise every variable when you declare it, and compile with -Wall, which warns about many of these.
Think of it like this: Types are like containers of fixed sizes in a kitchen: a 1-byte cup, a 4-byte mug, an 8-byte jug. Pour a jug of water into a mug and it overflows. And in C, a container you take from the shelf is not washed first: it may still contain whatever was in it before (garbage values).
Tip: Never write a leading zero on a decimal number: 010 is 8 in C, because a leading 0 means octal. This bites people storing PIN codes or roll numbers as integers.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Data types and their sizes · 1/6

Types and sizes

In this lesson you will learn C's data types and how big they are.

Prefer a video by a teacher? Find free videos on “c data types sizeof int long char signed unsigned stdint” on YouTube ↗

In real life: A sensor reading in an IoT device

A temperature sensor on a cold-storage warehouse sends readings as signed 16-bit values in tenths of a degree. The firmware stores them in int16_t, not int, because the network packet format fixes exactly 2 bytes, whatever compiler is used.

c
#include <stdio.h>
#include <stdint.h>

int main(void) {
    int16_t raw = -185;               /* -18.5 °C in tenths of a degree */
    printf("Temperature: %.1f C (%zu bytes)\n", raw / 10.0, sizeof raw);
    return 0;
}
Prints Temperature: -18.5 C (2 bytes)

Practice (0/3 done)

Task 1 · Question

On a typical 64-bit Linux system, what does printf("%zu", sizeof(long)) print?

Task 2 · Question

What does printf("%d\n", 010 + 1); print?

Task 3 · Code · Javascript

C's fixed-size integers wrap around. JavaScript has typed arrays with the same behaviour, which run here: write wrapUint8(n) that returns what a C uint8_t would hold after storing n (use a Uint8Array), and wrapInt8(n) for int8_t (Int8Array).

Quick quiz

Question 1

1.Which size is guaranteed to be 1 on every platform?

Question 2

2.Which printf format prints a size_t?

Question 3

3.Which header provides int32_t and uint8_t?

Question 4

4.int x; printf("%d", x); inside main prints…

Read more (free)

Before this, learn

This topic builds on these. If something here feels new, open them first.

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which size is guaranteed to be 1 on every platform?

Answer: sizeof(char)

sizeof(char) is 1 by definition.

Which printf format prints a size_t?

Answer: %zu

%zu (C99).

Which header provides int32_t and uint8_t?

Answer: <stdint.h>

stdint.h has the fixed-width types.

int x; printf("%d", x); inside main prints…

Answer: An unpredictable value (undefined behaviour)

Local variables are not initialised.

What is in an int variable declared inside main with int n; and no value?Related

Answer: Garbage: reading it is undefined behaviour

Local variables are not set to zero automatically. Always initialise them.

From Variables, types and constants

On a typical 64-bit system, sizeof(char *) is…Related

Answer: 8

All data pointers are 8 bytes on 64-bit systems.

From Addresses and pointers

In char a = 100, b = 100; int c = a + b; what is c?Related

Answer: 200

Promotion to int prevents overflow in the addition.

From Type conversion and casting

Which type should hold true or false?Related

Answer: boolean

boolean holds exactly true or false.

From Variables and primitive types

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “Getting started with C” before its exam: Input and output: printf and scanf.
  2. Module 1 exam: Getting started with C · 12 questions · 20 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Operators and control flow. 60 topics left in the course before the final exam.

← Previous: The structure of a C program