LearnFrenzy
Sign in Take a free test

Variables, Data Types and I/O · Lesson 4 of 35

Variables and Data Types in C

4 min read Updated Nov 7, 2026 Saurabh Samir

A variable is a named piece of memory that holds a value. In C, every variable has a type fixed when you declare it: the type decides how many bytes it uses, what values it can hold and which operations make sense. Choosing types carefully avoids some of C's nastiest bugs – overflow and lost precision.

In this lesson

  • Declaring and initialising variables
  • The basic types and their sizes
  • signed vs unsigned, and integer overflow
  • Naming rules and good habits

Declaring variables

#include <stdio.h>

int main(void) {
    int age = 20;               // declare and initialise
    float height = 5.6f;        // f suffix: a float literal
    double pi = 3.141592653589;
    char grade = 'A';           // single quotes: one character
    int a, b = 5, c;            // several at once (a and c are uninitialised!)
    a = 10;
    c = a + b;

    printf("age=%d height=%.1f pi=%.6f grade=%c\n", age, height, pi, grade);
    printf("a=%d b=%d c=%d\n", a, b, c);
    return 0;
}

Output

age=20 height=5.6 pi=3.141593 grade=A
a=10 b=5 c=15

Always initialise local variables

A local variable that isn't given a value contains whatever bytes were in that memory before – "garbage". Using it is undefined behaviour: the program may print random numbers or behave differently each run. Initialise every variable when you declare it.

Basic types and sizes

#include <stdio.h>

int main(void) {
    printf("char      : %zu byte\n",  sizeof(char));
    printf("short     : %zu bytes\n", sizeof(short));
    printf("int       : %zu bytes\n", sizeof(int));
    printf("long      : %zu bytes\n", sizeof(long));
    printf("long long : %zu bytes\n", sizeof(long long));
    printf("float     : %zu bytes\n", sizeof(float));
    printf("double    : %zu bytes\n", sizeof(double));
    return 0;
}

Output

char      : 1 byte
short     : 2 bytes
int       : 4 bytes
long      : 8 bytes
long long : 8 bytes
float     : 4 bytes
double    : 8 bytes

sizeof gives a size in bytes, printed with %zu. These are the sizes on 64-bit Linux and macOS. The C standard only guarantees minimums – on 64-bit Windows long is 4 bytes, and old 16-bit compilers like Turbo C have a 2-byte int. When you need an exact size, use int32_t, int64_t and friends from <stdint.h>.

TypeTypical sizeTypical range / precisionprintf
char1 byte−128 to 127 (or 0–255)%c / %d
int4 bytes−2,147,483,648 to 2,147,483,647%d
unsigned int4 bytes0 to 4,294,967,295%u
long long8 bytesabout ±9.2 × 10¹⁸%lld
float4 bytesabout 6–7 significant digits%f
double8 bytesabout 15–16 significant digits%f (printf), %lf (scanf)

float vs double

#include <stdio.h>

int main(void) {
    float f = 0.1f + 0.2f;
    double d = 0.1 + 0.2;
    printf("float : %.10f\n", f);
    printf("double: %.17f\n", d);
    printf("%s\n", d == 0.3 ? "equal" : "not equal");
    return 0;
}

Output

float : 0.3000000119
double: 0.30000000000000004
not equal

Decimal fractions like 0.1 can't be stored exactly in binary. Prefer double over float for accuracy, and never compare floating-point values with == – check whether the difference is tiny: fabs(a - b) < 1e-9.

signed, unsigned and overflow

#include <stdio.h>
#include <limits.h>

int main(void) {
    printf("INT_MAX  = %d\n", INT_MAX);
    printf("INT_MIN  = %d\n", INT_MIN);
    printf("UINT_MAX = %u\n", UINT_MAX);

    unsigned int u = 0;
    u = u - 1;                         // unsigned arithmetic wraps around
    printf("0u - 1   = %u\n", u);

    long long population = 1400000000LL * 6;   // too big for int: use long long
    printf("big      = %lld\n", population);
    return 0;
}

Output

INT_MAX  = 2147483647
INT_MIN  = -2147483648
UINT_MAX = 4294967295
0u - 1   = 4294967295
big      = 8400000000

Interview angle: overflow

Unsigned integers wrap around predictably (modulo 2ⁿ). Signed overflow – e.g. INT_MAX + 1 – is undefined behaviour: the compiler may assume it never happens and the result can't be relied on. Use a wider type (long long) when values can grow large, such as factorials, sums of big arrays or money in paise.

Naming rules

  • Letters, digits and underscores only; must not start with a digit; case-sensitive (total ≠ Total).
  • Can't be a keyword (int, return, while…).
  • Use meaningful names: total_marks, not tm. C programmers usually write snake_case.
  • Names starting with an underscore and a capital letter (_Value) are reserved for the compiler – avoid them.

Practice

Try it yourself

  1. Store a student's roll number, percentage and section letter, and print them on one line.

    Show solution
    #include <stdio.h>
    
    int main(void) {
        int roll = 42;
        double percentage = 87.25;
        char section = 'B';
        printf("Roll %d | %.2f%% | Section %c\n", roll, percentage, section);
        return 0;
    }

    Output

    Roll 42 | 87.25% | Section B

Quick check

What is the value of an uninitialised local int?

Indeterminate ("garbage"); reading it is undefined behaviour.

Which format specifier prints a size_t from sizeof?

%zu.

Is signed integer overflow well defined in C?

No – it's undefined behaviour. Unsigned overflow wraps around.

Summary

  • Every variable has a type that fixes its size and range; always initialise locals.
  • Use int for counts, long long for big numbers, double for decimals, char for characters.
  • Floating point is approximate; signed overflow is undefined – choose wide enough types.

Finished this lesson?

Mark it complete to track your progress, then carry on with the next lesson.

Next lesson

Search LearnFrenzy

Esc

Quick links