DEV Community

Cover image for Variables Are Memory Addresses
Shankar L
Shankar L

Posted on

Variables Are Memory Addresses

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.

Top comments (0)