</>
Skip to content
C lessons (7/28)

C — Variables

Declaration and initialization

Variables must be declared before use:

#include <stdio.h>

int main() {
    int age;           // Declaration
    age = 30;          // Assignment

    int score = 95;    // Declaration + initialization
    float pi = 3.14;   // Float declaration
    char grade = 'A';  // Character declaration

    printf("Age: %d, Score: %d, Grade: %c\n", age, score, grade);
    return 0;
}

Naming rules

  • Must start with a letter or underscore _
  • Can only contain letters, numbers, and underscores
  • Are case-sensitive (Count ≠ count)
  • Cannot be a reserved keyword
int count;      // Valid
int _private;   // Valid
int my_var2;    // Valid
int 2count;     // Invalid: starts with a number
int my-var;     // Invalid: hyphens not allowed

Data types at a glance

#include <stdio.h>

int main() {
    int integer = 42;
    float decimal = 3.14;
    double precise = 3.141592653589793;
    char letter = 'A';
    _Bool flag = 1;  // C99+

    printf("int: %d\n", integer);
    printf("float: %.2f\n", decimal);
    printf("double: %.15f\n", precise);
    printf("char: %c\n", letter);
    printf("bool: %d\n", flag);
    return 0;
}

Scope

Variables are visible only within the block where they're declared:

#include <stdio.h>

int main() {
    int x = 10; // Visible from here to end of main

    if (x > 5) {
        int y = 20; // Visible only inside this if block
        printf("x=%d, y=%d\n", x, y); // Both accessible
    }

    printf("x=%d\n", x);   // OK
    // printf("%d", y);     // Error: y is out of scope
    return 0;
}

Storage classes

C provides four storage classes:

#include <stdio.h>

// auto: default for local variables
void example_auto() {
    auto int x = 10; // Same as: int x = 10;
    printf("auto: %d\n", x);
}

// static: persists between function calls
void example_static() {
    static int count = 0; // Initialized only once
    count++;
    printf("static count: %d\n", count);
}

// extern: declares a variable defined elsewhere
extern int global_counter;

// register: suggests CPU register storage (rarely used today)
void example_register() {
    register int fast_var = 100;
    printf("register: %d\n", fast_var);
}

int main() {
    example_auto();
    example_static();
    example_static(); // count = 2
    example_static(); // count = 3
    return 0;
}

Type sizes

Use sizeof to check type sizes:

#include <stdio.h>

int main() {
    printf("char:     %zu bytes\n", sizeof(char));      // 1
    printf("short:    %zu bytes\n", sizeof(short));     // 2
    printf("int:      %zu bytes\n", sizeof(int));       // 4
    printf("long:     %zu bytes\n", sizeof(long));      // 4 or 8
    printf("long long:%zu bytes\n", sizeof(long long)); // 8
    printf("float:    %zu bytes\n", sizeof(float));     // 4
    printf("double:   %zu bytes\n", sizeof(double));    // 8
    return 0;
}

Fixed-width types

Use <stdint.h> for exact sizes:

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

int main() {
    int8_t   a = -128;    // Exactly 1 byte
    int16_t  b = -32768;  // Exactly 2 bytes
    int32_t  c = -2147483648; // Exactly 4 bytes
    int64_t  d = -9223372036854775808LL; // Exactly 8 bytes

    uint8_t  e = 255;     // Unsigned 1 byte
    uint16_t f = 65535;   // Unsigned 2 bytes

    printf("int32_t: %d\n", c);
    printf("uint8_t: %u\n", e);
    return 0;
}

Implicit and explicit conversion

#include <stdio.h>

int main() {
    // Implicit conversion (int → float)
    int a = 7;
    float b = a; // 7.0
    printf("%.1f\n", b);

    // Explicit cast
    int x = 5, y = 2;
    float result = (float)x / y; // 2.5 (not 2)
    printf("%.1f\n", result);

    // Truncation warning
    double pi = 3.14159;
    int truncated = (int)pi; // 3 — decimal part lost
    printf("%d\n", truncated);

    return 0;
}

Undefined behavior

Avoid these mistakes:

#include <stdio.h>

int main() {
    // Using an uninitialized variable
    int x;
    // printf("%d\n", x); // Undefined behavior!

    // Integer overflow
    int max = 2147483647;
    // max++; // Undefined behavior in signed integers

    // Division by zero
    // int zero = 0;
    // int bad = 42 / zero; // Undefined behavior!

    printf("Always initialize variables before use.\n");
    return 0;
}

Best practices

  • Always initialize variables before use
  • Use the smallest type that fits your data
  • Prefer fixed-width types from <stdint.h> when size matters
  • Avoid unsigned types unless you specifically need modulo arithmetic
  • Initialize static variables explicitly (even though they default to 0)

Mini Practice

Write C code that:

  1. Declares variables of each basic type and prints their sizes with sizeof
  2. Demonstrates scope by declaring a variable inside an if block
  3. Uses a static variable to count function calls
  4. Shows implicit and explicit type conversion

Up Next

In the next lesson, you'll learn about Data Types — the full set of types in C.

Related Topics

Frequently Asked Questions about Variables

What is Variables in C?

Variables is a fundamental concept in C. This lesson explains it step by step with clear examples, making it easy for beginners to understand.

How do I learn Variables?

Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Variables.

Why is Variables important in C?

Variables is essential for C development. Understanding this concept will help you write better code and solve real-world problems more effectively.