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.
📚 Table of Contents
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
intorchar, 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.
| Term | Meaning | Example |
|---|---|---|
| Declaration | Tells the compiler a variable's name and type exist | extern int count; |
| Definition | Declaration that also reserves memory for the variable | int count; |
| Initialization | Giving the variable a value at the moment it is defined | int count = 0; |
| Assignment | Changing the value later, after it already exists | count = 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
totalandTotalare different variables - You cannot use a keyword such as
int,return, orwhileas a name - Spaces and symbols like
-or@are not allowed
| Name | Valid? | Reason |
|---|---|---|
age | Yes | Letters only |
total_marks | Yes | Underscore is allowed |
student2 | Yes | Digit is fine after the first character |
2student | No | Starts with a digit |
my-var | No | Hyphen is not allowed |
total marks | No | Contains a space |
int | No | Reserved 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
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 variable | Global variable | |
|---|---|---|
| Declared | Inside a function or block | Outside all functions |
| Visible in | That block only | Rest of the file |
| Default value | Indeterminate (garbage) if not initialized | Zero if not initialized |
| Lifetime | Created on entry, destroyed on exit | Entire 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
staticinside a function keeps the value alive between calls- Compile with warnings on (
-Wall) to catch many of these mistakes early


0 Comments