Variables Are Memory Addresses
Why should you care?
You write:
int age = 20;
Enter fullscreen mode Exit fullscreen mode
It looks like age is simply a box containing the number 20.
But what actually happens in memory?
Where is 20 stored?
How does the computer find it?
And what exactly happens when you write:
age = 21;
Enter fullscreen mode Exit fullscreen mode
Understanding the relationship between variables, memory locations, and addresses is one of the most important steps toward understanding pointers, references, stack memory, heap memory, and low-level programming.
There is one important correction to the title:
A variable is not literally a memory address. A variable is a programming-language abstraction associated with a value and, when applicable, a storage location. That location can have a memory address, but the compiler may also keep the value in a CPU register or optimize the variable away entirely.
The Problem
Consider this C program:
#include <stdio.h>
int main() {
int age = 20;
printf("%d\n", age);
return 0;
}
Enter fullscreen mode Exit fullscreen mode
When you write:
int age = 20;
Enter fullscreen mode Exit fullscreen mode
you are telling the compiler that you want a variable called age containing an integer value.
Conceptually, memory might look like:
Memory
┌───────────────┐
│ Address │
├───────────────┤
│ 0x7FFE1000 │ → 20
└───────────────┘
Enter fullscreen mode Exit fullscreen mode
The address is where the data can be located.
The variable name age is how your source code refers to that value.
So we have:
Variable
↓
Storage location
↓
Value
Enter fullscreen mode Exit fullscreen mode
But the exact implementation is decided by the compiler and runtime.
The Concept
A memory address identifies a location in an address space.
Imagine memory as a huge collection of numbered locations:
Address Value
0x1000 → 42
0x1004 → 17
0x1008 → 99
0x100C → 5
Enter fullscreen mode Exit fullscreen mode
The numbers on the left are addresses.
The numbers on the right are stored values.
When a program needs data, the processor ultimately needs to access the relevant storage location.
For example:
age = 20
Enter fullscreen mode Exit fullscreen mode
might conceptually correspond to:
Address
0x1000
↓
Value
20
Enter fullscreen mode Exit fullscreen mode
The address tells the computer where.
The value tells it what.
Simple Explanation
Think of your house.
Your address tells someone where your house is.
Your name identifies who lives there.
Your belongings are the actual things stored inside.
Similarly:
Variable name → age
Memory address → 0x1000
Stored value → 20
Enter fullscreen mode Exit fullscreen mode
These are three different concepts.
age
↓
"the integer variable I'm referring to"
0x1000
↓
"where the storage is located"
20
↓
"the value currently stored there"
Enter fullscreen mode Exit fullscreen mode
This distinction becomes extremely important when learning pointers.
Real-world Analogy
Imagine a library.
Every shelf has a location:
Shelf A12
Shelf B27
Shelf C42
Enter fullscreen mode Exit fullscreen mode
A book has a title:
"Operating Systems"
Enter fullscreen mode Exit fullscreen mode
And the book contains information.
So:
Book name → Operating Systems
Location → Shelf B27
Content → Book's pages
Enter fullscreen mode Exit fullscreen mode
Similarly:
Variable name → age
Memory address → 0x1000
Value → 20
Enter fullscreen mode Exit fullscreen mode
The variable name is a convenient way for the programmer to refer to stored data.
Code Example
C allows us to see the address of a variable using the & operator.
#include <stdio.h>
int main() {
int age = 20;
printf("Value: %d\n", age);
printf("Address: %p\n", (void*)&age);
return 0;
}
Enter fullscreen mode Exit fullscreen mode
You might get output similar to:
Value: 20
Address: 0x7ffd23a4
Enter fullscreen mode Exit fullscreen mode
The exact address will vary between executions.
Now look at the difference:
age
Enter fullscreen mode Exit fullscreen mode
means:
Give me the value of age.
Enter fullscreen mode Exit fullscreen mode
While:
&age
Enter fullscreen mode Exit fullscreen mode
means:
Give me the address of age.
Enter fullscreen mode Exit fullscreen mode
So:
age → value
&age → address
Enter fullscreen mode Exit fullscreen mode
This is the foundation of pointers.
Pointers
A pointer is a variable that stores an address.
For example:
#include <stdio.h>
int main() {
int age = 20;
int *ptr = &age;
printf("Value: %d\n", age);
printf("Address: %p\n", (void*)&age);
printf("Pointer contains: %p\n", (void*)ptr);
return 0;
}
Enter fullscreen mode Exit fullscreen mode
Conceptually:
age
┌──────────────┐
│ 20 │
└──────────────┘
↑
│
│ address
│
ptr
┌──────────────┐
│ 0x7FFD... │
└──────────────┘
Enter fullscreen mode Exit fullscreen mode
The pointer doesn’t contain 20.
It contains the address of the memory location where 20 is stored.
Dereferencing
Now we can use the pointer to access the value.
int age = 20;
int *ptr = &age;
printf("%d\n", *ptr);
Enter fullscreen mode Exit fullscreen mode
Output:
20
Enter fullscreen mode Exit fullscreen mode
The * operator here means:
Go to the address stored in ptr
and retrieve the value there.
Enter fullscreen mode Exit fullscreen mode
So:
ptr
↓
Address
↓
Memory
↓
20
Enter fullscreen mode Exit fullscreen mode
This operation is called dereferencing.
Changing a Value Through a Pointer
You can also modify the value through its address.
int age = 20;
int *ptr = &age;
*ptr = 21;
printf("%d\n", age);
Enter fullscreen mode Exit fullscreen mode
Output:
21
Enter fullscreen mode Exit fullscreen mode
What happened?
age
↓
Memory location
↓
20
*ptr = 21
age
↓
Memory location
↓
21
Enter fullscreen mode Exit fullscreen mode
The pointer allowed us to access the same storage location indirectly.
Common Mistakes
Mistake 1: Thinking a variable is an address
This is the biggest misconception.
A variable is a language-level abstraction.
It may correspond to a memory location, but it does not necessarily have a permanent physical address.
For example, a compiler may keep:
int x = 10;
Enter fullscreen mode Exit fullscreen mode
inside a CPU register.
In that case, there may be no RAM location associated with x during some part of execution.
Mistake 2: Confusing & and *
In C:
&x
Enter fullscreen mode Exit fullscreen mode
means:
Address of x
Enter fullscreen mode Exit fullscreen mode
while:
*x
Enter fullscreen mode Exit fullscreen mode
when x is a pointer, means:
Value at the address stored in x
Enter fullscreen mode Exit fullscreen mode
Remember:
& → address of
* → dereference
Enter fullscreen mode Exit fullscreen mode
Mistake 3: Thinking addresses never change
A variable’s storage location can change during execution depending on the language, runtime, compiler, stack behavior, and memory management.
Modern operating systems also use virtual memory, meaning the address visible to a process is generally a virtual address, not a direct physical RAM address.
Mistake 4: Assuming every variable is stored in RAM
Not necessarily.
A compiler can optimize a variable into:
- CPU registers
- Memory
- Another optimized representation
- No storage at all
For example:
int x = 10;
int y = x + 5;
Enter fullscreen mode Exit fullscreen mode
The compiler may determine that storing x in memory is unnecessary.
Advanced Notes
Virtual Addresses
The address you see in a program is generally a virtual address.
For example:
0x7FFE1234
Enter fullscreen mode Exit fullscreen mode
does not necessarily mean that physical RAM location 0x7FFE1234 contains the data.
Instead:
Virtual Address
↓
Memory Management Unit
↓
Physical Memory
Enter fullscreen mode Exit fullscreen mode
The operating system and hardware manage this translation.
This is one of the reasons processes can have isolated address spaces.
Stack Variables
Consider:
void function() {
int x = 10;
}
Enter fullscreen mode Exit fullscreen mode
x has automatic storage duration and is commonly associated with the function’s stack frame.
Conceptually:
Stack
┌──────────────┐
│ Local data │
├──────────────┤
│ x = 10 │
├──────────────┤
│ Return info │
└──────────────┘
Enter fullscreen mode Exit fullscreen mode
The exact implementation can differ because compilers may optimize local variables into registers or eliminate them.
Heap Variables
Dynamically allocated memory is commonly associated with the heap.
For example:
int *ptr = malloc(sizeof(int));
*ptr = 50;
Enter fullscreen mode Exit fullscreen mode
Conceptually:
ptr
↓
Address
↓
Heap
┌──────────────┐
│ 50 │
└──────────────┘
Enter fullscreen mode Exit fullscreen mode
Here, ptr stores an address pointing to dynamically allocated storage.
What About Java?
Java makes this concept slightly different.
Consider:
int age = 20;
Enter fullscreen mode Exit fullscreen mode
You cannot directly obtain the raw memory address of age using normal Java language features.
Java intentionally hides direct memory manipulation from ordinary application code.
For objects:
Person person = new Person();
Enter fullscreen mode Exit fullscreen mode
person is better understood as a reference to an object, not as a C-style pointer that programmers can freely perform arithmetic on.
This abstraction provides safety and allows the JVM and garbage collector to manage memory.
So the relationship is:
C
Variable → Memory location → Address
Java
Variable → Value or Reference → Object
Enter fullscreen mode Exit fullscreen mode
The JVM decides how and where objects are actually represented.
The Bigger Picture
This concept connects several important areas of computer science.
Variables
↓
Memory
↓
Addresses
↓
Pointers / References
↓
Stack & Heap
↓
Virtual Memory
↓
Operating System
↓
CPU
Enter fullscreen mode Exit fullscreen mode
Once you understand this chain, concepts such as:
- Pointers
- References
- Arrays
- Function calls
- Stack frames
- Dynamic memory
- Garbage collection
- Virtual memory
become much easier to understand.
Summary
A variable is not literally a memory address.
Instead, think of three separate concepts:
Variable
↓
Storage
↓
Value
Enter fullscreen mode Exit fullscreen mode
When storage has an address, we can think of:
Variable → Address → Value
Enter fullscreen mode Exit fullscreen mode
For example:
age
↓
0x7FFE1000
↓
20
Enter fullscreen mode Exit fullscreen mode
In C:
age
Enter fullscreen mode Exit fullscreen mode
accesses the value.
&age
Enter fullscreen mode Exit fullscreen mode
gets its address.
And:
*ptr
Enter fullscreen mode Exit fullscreen mode
dereferences an address stored in a pointer.
The deeper lesson is that programming languages give us abstractions over the physical machine. Sometimes a variable corresponds to memory, sometimes it lives in a register, and sometimes the compiler eliminates it completely.
Understanding that distinction is the first step toward thinking like a systems programmer.