Variables in C: Declaration, Initialization & Scope

Variables in C: age, marks and grade shown as labelled boxes with type and value

Quick question before we start. What do you think this program prints?

#include <stdio.h>

int main(void) {
    int x;
    printf("%d\n", x);
    return 0;
}

The honest answer: nobody can say. Reading a variable that was never given a value is undefined behavior, so the compiler is free to do anything. The variable x was declared but never initialized, so it holds whatever happened to be in that memory location. Bugs like this are exactly why understanding declaration, initialization, and scope matters before you move on to bigger C topics.

In this guide you will learn what a variable really is, the difference between declaring, defining, and initializing it, the rules for naming variables, how local and global scope work, and the mistakes beginners make most often. If you have not seen how a full program is laid out yet, read Structure of a C Program first.

What Is a Variable in C?

A variable is a named location in memory that stores a value your program can read and change while it runs. Every variable in C has three things:

  • A type, such as int or char, which decides what kind of value it holds and how much memory it uses
  • A name, which you use to refer to it in code
  • A value, which is the data currently stored in it

You can compile and run every example in this post like this:

gcc -std=c99 -Wall -Wextra program.c -o program
./program

-Wall -Wextra turn on helpful compiler warnings. On Windows, run program.exe instead of ./program.

Think of a variable as a labelled box. The type decides the size and shape of the box, the name is the label on it, and the value is what is inside right now.

#include <stdio.h>

int main(void) {
    int age = 21;
    printf("Age is %d\n", age);

    age = 22;
    printf("Age is now %d\n", age);
    return 0;
}

Output:

Age is 21
Age is now 22

The same box (age) held 21 first, and then 22. That is why it is called a variable.

Declaration, Definition and Initialization

These four words are often used as if they mean the same thing. They do not.

TermMeaningExample
DeclarationTells the compiler a variable's name and type existextern int count;
DefinitionDeclaration that also reserves memory for the variableint count;
InitializationGiving the variable a value at the moment it is definedint count = 0;
AssignmentChanging the value later, after it already existscount = 5;

For ordinary local variables like int age;, the declaration is also the definition, so you will usually just hear it called "declaring a variable". The distinction becomes important when a program is split across multiple files, because extern lets one file say "this variable exists, it is defined somewhere else".

#include <stdio.h>

int main(void) {
    int age;            /* declared, no value yet */
    age = 21;           /* assignment             */
    int marks = 85;     /* declared + initialized */

    int a = 1, b = 2, c;   /* several at once; c has no value yet */
    c = a + b;

    printf("age = %d, marks = %d, c = %d\n", age, marks, c);
    return 0;
}

Output:

age = 21, marks = 85, c = 3

Where Can You Declare Variables?

In the older C89/ANSI C standard, local variables had to be declared at the top of a block, before any other statements. From C99 onward, you can declare a variable close to where you first use it. The example above (int marks = 85; after a statement) therefore needs a C99-or-later compiler mode. If you are curious how the standards differ, see ANSI C Standards (C89, C99, C11, C17 & C23).

Rules for Naming Variables

C is strict about names, which are officially called identifiers.

  • Use letters, digits, and underscores only
  • The first character cannot be a digit
  • Names are case-sensitive, so total and Total are different variables
  • You cannot use a keyword such as int, return, or while as a name
  • Spaces and symbols like - or @ are not allowed
NameValid?Reason
ageYesLetters only
total_marksYesUnderscore is allowed
student2YesDigit is fine after the first character
2studentNoStarts with a digit
my-varNoHyphen is not allowed
total marksNoContains a space
intNoReserved keyword

Good names make code readable. Prefer total_marks over tm. Also avoid names that start with an underscore followed by a capital letter, or that start with a double underscore, because the C standard reserves those for the implementation.

Scope of Variables

Scope is the part of the program where a variable's name can be used. Outside its scope, the compiler behaves as if the variable does not exist. For beginners, two kinds of scope matter most:

  • Block scope (local): the variable is visible only inside the { } block where it is declared, including function bodies
  • File scope (global): the variable is declared outside every function and is visible from that point to the end of the file
C programming infographic showing global, local, and block variable scope

Block Scope

#include <stdio.h>

int main(void) {
    int x = 5;

    if (x > 0) {
        int y = 20;                       /* y exists only in this block */
        printf("x = %d, y = %d\n", x, y);
    }

    /* printf("%d\n", y);  would fail: 'y' undeclared here */
    return 0;
}

Output:

x = 5, y = 20

Here y is created when the if block starts and is gone when it ends. Trying to use y after the closing brace gives a compile error.

Local vs Global Variables

#include <stdio.h>

int globalCount = 100;     /* global: visible to every function below */

void show(void) {
    printf("Inside show(): globalCount = %d\n", globalCount);
}

int main(void) {
    int localCount = 10;   /* local: visible only inside main() */

    printf("Inside main(): localCount = %d\n", localCount);
    printf("Inside main(): globalCount = %d\n", globalCount);
    show();
    return 0;
}

Output:

Inside main(): localCount = 10
Inside main(): globalCount = 100
Inside show(): globalCount = 100

show() can read globalCount but cannot see localCount, because that belongs to main() only.

Local variableGlobal variable
DeclaredInside a function or blockOutside all functions
Visible inThat block onlyRest of the file
Default valueIndeterminate (garbage) if not initializedZero if not initialized
LifetimeCreated on entry, destroyed on exitEntire program run

Global variables are convenient, but they can be changed from anywhere, which makes bugs harder to trace. Prefer local variables and pass values through function parameters whenever you can.

Variable Shadowing

If a local variable has the same name as a global one, the local variable shadows the global inside its scope.

#include <stdio.h>

int value = 50;            /* global */

int main(void) {
    int value = 10;        /* local, hides the global one */
    printf("value = %d\n", value);
    return 0;
}

Output:

value = 10

The global value still exists, but inside main() the name refers to the local one. Shadowing is legal but confusing, so avoid it in real code.

Static Local Variables

Normally, a local variable is destroyed when its function returns. Adding the keyword static changes its lifetime without changing its scope: the variable is created once and keeps its value between calls, but it is still visible only inside that function.

#include <stdio.h>

void counter(void) {
    int normal = 0;
    static int remembered = 0;

    normal++;
    remembered++;
    printf("normal = %d, static = %d\n", normal, remembered);
}

int main(void) {
    counter();
    counter();
    counter();
    return 0;
}

Output:

normal = 1, static = 1
normal = 1, static = 2
normal = 1, static = 3

normal restarts at 0 on every call. remembered is initialized only once and keeps counting.

How Much Memory Does a Variable Take?

When you define a variable, the compiler reserves enough bytes for its type. You can check the size with sizeof:

#include <stdio.h>

int g;   /* global, not initialized */

int main(void) {
    int  a = 7;
    char c = 'A';

    printf("sizeof(a) = %zu bytes\n", sizeof(a));
    printf("sizeof(c) = %zu byte\n", sizeof(c));
    printf("g = %d\n", g);
    return 0;
}

Output (typical):

sizeof(a) = 4 bytes
sizeof(c) = 1 byte
g = 0

The size of int depends on the platform; 4 bytes is common on modern systems. Notice that g prints 0 even though we never set it. Global and static variables are automatically zero-initialized, but local variables are not. For how source code becomes a running program that gets this memory, see How the C Compilation Process Works. To read values into variables from the keyboard, see Master printf and scanf in C.

Common Mistakes

Mistake 1: Using a Local Variable Before Initializing It

int total;
total = total + 10;    /* total had no starting value */

The result is unpredictable because total began with an indeterminate value. Fix: always give local variables a starting value.

int total = 0;
total = total + 10;

Mistake 2: Using a Variable Outside Its Scope

for (int i = 0; i < 3; i++) {
    /* ... */
}
printf("%d\n", i);     /* error: 'i' undeclared */

The loop counter i lives only inside the for statement (in C99 and later). Fix: declare int i; before the loop if you need it afterwards.

Mistake 3: Writing = Instead of ==

#include <stdio.h>

int main(void) {
    int x = 3;
    if (x = 5) {
        printf("This always runs, x = %d\n", x);
    }
    return 0;
}

Output:

This always runs, x = 5

x = 5 is an assignment, not a comparison. It sets x to 5 and the condition becomes true. Fix: use x == 5 to compare. Many compilers warn about this if you enable warnings with -Wall.

Mistake 4: Declaring the Same Variable Twice in One Scope

int a = 1;
int a = 2;     /* error: redefinition of 'a' */

Two variables with the same name cannot exist in the same scope. Fix: give them different names, or simply assign the new value with a = 2;. (The exact error message differs between compilers.)

Mistake 5: Overusing Global Variables

When many functions change the same global, it becomes hard to know which one caused a wrong value. Keep variables as local as possible, and pass data using function arguments.

Practice Questions

Q1. What does this program print?

#include <stdio.h>

int main(void) {
    int x = 5;
    {
        int x = 10;
    }
    printf("%d\n", x);
    return 0;
}

Q2. If counter() from the static example is called 5 times, what does the last line print?

Q3. Which of these are invalid variable names? _total, 9lives, float, user_name, my score

Show answers

A1. 5. The inner x exists only inside its own braces. The printf sees the outer x.

A2. normal = 1, static = 5

A3. 9lives (starts with a digit), float (keyword), my score (contains a space).

Frequently Asked Questions

What is the difference between declaration and definition in C?

A declaration tells the compiler that a name and type exist. A definition also reserves memory for it. For ordinary local variables like int x;, the declaration is also a definition. extern int x; is a declaration only.

What value does an uninitialized variable have in C?

A local variable has an indeterminate value, so reading it gives unpredictable results. Global and static variables, on the other hand, start at zero.

What is the scope of a variable in C?

Scope is the region of code where a variable's name is visible. A variable declared inside a block is visible only within that block. A variable declared outside all functions is visible from its declaration to the end of the file.

Can two variables have the same name in C?

Not in the same scope. In different scopes they can, for example a local variable and a global one. The local variable then shadows the global one inside its block.

What does the static keyword do to a local variable?

It makes the variable keep its value between function calls. It is initialized only once, but it is still visible only inside the function where it is declared.

Conclusion

Variables are the foundation of every C program, and most beginner bugs trace back to the same few ideas. The points worth remembering:

  • A variable has a type, a name, and a value
  • Declaration introduces a name, definition reserves memory, initialization gives a first value
  • Local variables start with garbage unless you initialize them; global and static ones start at zero
  • A variable is usable only within its scope, and an inner variable can shadow an outer one
  • static inside a function keeps the value alive between calls
  • Compile with warnings on (-Wall) to catch many of these mistakes early

Post a Comment

0 Comments