LearnContact
Lesson 1710 min read

Pointers

References provide another name for an existing object, but C++ also allows us to work directly with memory addresses. In this lesson, you will learn how pointers store addresses and how to access and modify values through them.

Introduction

In the previous lesson, you learned about references, which provide another name for an existing object. C++ also allows programs to work with the memory address of an object.

Simple Variable
int number = 100;

When this variable is created, the computer stores its value somewhere in memory. The exact address is chosen by the system and may be different each time the program runs.

Conceptual Memory
Variable: number

Address          Value
0x1000 ────────► 100

Normally, we use the variable name to work with the value. Sometimes, however, a program needs to store and work with the address of an object itself.

The Solution

C++ provides pointers, which are objects that can store memory addresses.

What is a Pointer?

A pointer is a variable that stores the memory address of another object.

An ordinary variable stores a value directly, while a pointer stores an address that can identify another object.

Variable and Pointer
int number = 100;
int *ptr = &number;
Relationship
ptr
 │
 │ stores address of number
 ▼
number ─────► 100
ObjectStores
numberThe integer value 100
ptrThe address of number
Simple Definition

A pointer is a variable whose value is a memory address.

Why Do We Need Pointers?

Pointers are an important part of C++ because they allow programs to represent optional objects, build dynamic structures, manage resources, interact with low-level systems, and work with dynamically allocated memory.

Without Pointers

  • Dynamic linked structures would be difficult to represent.
  • Explicit dynamic memory management would not be possible in the same way.
  • Interfacing with many low-level APIs would become difficult.
  • Representing an optional object through a null address would not be available.
  • Many system-level programming techniques would be unavailable.

With Pointers

  • Store and work with object addresses.
  • Represent an optional object using nullptr.
  • Build linked lists, trees, and graphs.
  • Work with dynamically allocated objects.
  • Interact with operating systems, hardware, and C-style APIs.

Address Storage

Pointers can store the address of compatible objects.

Indirect Access

Pointers can access and modify objects through their addresses.

Dynamic Memory

Pointers are fundamental when working directly with dynamically allocated objects.

Data Structures

Linked lists, trees, and graphs use links between objects.

Optional State

A pointer can hold nullptr to represent that it currently points to no object.

Low-Level Programming

Pointers are widely used when interacting with system APIs and memory-oriented interfaces.

Real-World Analogy

Imagine a hotel. A guest named Rahul is staying in room 101. Instead of carrying Rahul himself, a note can simply contain his room number.

Hotel Analogy
Pointer Note
┌─────────────┐
│ Room 101    │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│ Room 101    │
│ Rahul       │
└─────────────┘

The room number tells you where Rahul can be found. Similarly, a pointer stores an address that identifies where an object can be accessed.

Object Exists
Object Has an Address
Pointer Stores the Address
Address Leads to the Object
Address Analogy

The pointer is like a note containing a room number. The address tells the program where the target object can be found.

Variables and Memory

Every object used by a running program occupies storage. Consider the following integer variable.

Variable Declaration
int number = 100;

Conceptually, the program has a value stored at some memory address.

Conceptual Memory Layout
Variable Name: number

Memory Address       Stored Value
─────────────────────────────────
0x1000               100
PropertyExample
Variable Namenumber
Data Typeint
Stored Value100
Memory Address0x1000 (example only)
Addresses Are Not Fixed

Addresses shown in lessons are conceptual examples. Real memory addresses are chosen by the system and may change between executions.

Pointer Declaration & Address-of Operator

To declare a pointer, use the * symbol in the declaration.

Pointer Declaration Syntax
data_type *pointer_name;
Example
int *ptr;

This declares ptr as a pointer to int. It means ptr can store the address of a compatible int object.

PartMeaning
intThe type of object the pointer can point to
*Indicates a pointer declarator in this declaration
ptrThe pointer variable name

To obtain the address of an object, use the address-of operator &.

Address-of Operator
int number = 100;

std::cout << &number;

The expression &number produces the address of number.

Store Address in a Pointer
int number = 100;
int *ptr = &number;
Create number
Use &number
Obtain Address
Store Address in ptr
* and & Have Different Meanings Depending on Context

In int *ptr, * declares a pointer. In *ptr, it dereferences a pointer. In &number, & obtains an address. In int &ref, & declares a reference.

Example 1: Displaying Memory Address

Example 1
#include <iostream>

int main()
{
    int number = 100;

    std::cout << number << std::endl;
    std::cout << &number;

    return 0;
}

Explanation

  • number is created with the value 100.
  • std::cout << number displays the stored value.
  • &number produces the address of number.
  • std::cout << &number displays that address.
Possible Output
100
0x61ff08
Your Address Will Be Different

The displayed address is only an example. The actual address may differ every time the program runs.

Example 2: Creating a Pointer

The address of an object can be stored in a compatible pointer.

Example 2
#include <iostream>

int main()
{
    int number = 100;
    int *ptr = &number;

    std::cout << ptr;

    return 0;
}

Explanation

  • number stores the integer value 100.
  • int *ptr declares a pointer to int.
  • &number obtains the address of number.
  • ptr stores that address.
  • Printing ptr displays the address stored inside the pointer.
Conceptual Memory Representation
number
Address: 0x1000
┌─────────────┐
│    100      │
└─────────────┘
      ▲
      │
      │ points to
      │
ptr
Address: 0x2000
┌─────────────┐
│   0x1000    │
└─────────────┘
VariableExample AddressStored Value
number0x1000100
ptr0x20000x1000
The Pointer Is Also a Variable

ptr has its own storage and its own address. The value stored inside ptr is the address of number.

The Dereference Operator (*)

Once a pointer stores the address of an object, the dereference operator * can be used to access the object through that pointer.

Dereference Syntax
*pointer_name
Example
int number = 100;
int *ptr = &number;

std::cout << *ptr;

The expression *ptr means: access the object located at the address stored in ptr.

ptr Stores Address
Dereference *ptr
Follow the Address
Access the Target Object
Dereferencing Concept
ptr contains 0x1000
        │
        ▼
Go to address 0x1000
        │
        ▼
Access value 100
Dereference Meaning

Dereferencing follows the address stored in a valid pointer and accesses the pointed-to object.

Example 3: Dereferencing a Pointer

Example 3
#include <iostream>

int main()
{
    int number = 100;
    int *ptr = &number;

    std::cout << *ptr;

    return 0;
}

Step-by-Step Explanation

  • number is created with the value 100.
  • &number obtains the address of number.
  • ptr stores the address of number.
  • *ptr follows the stored address.
  • The value of the pointed-to object is accessed.
  • The program displays 100.
Output
100
ExpressionMeaning
numberThe value stored in number
&numberThe address of number
ptrThe address stored in the pointer
*ptrThe object accessed through the pointer
Remember the Relationship

If ptr stores &number, then *ptr accesses number.

Example 4: Modifying a Variable Using a Pointer

A valid non-const pointer can also be used to modify the object to which it points.

Example 4
#include <iostream>

int main()
{
    int number = 100;
    int *ptr = &number;

    *ptr = 250;

    std::cout << number;

    return 0;
}
number Stores 100
ptr Stores Address of number
Dereference ptr
Assign 250 to Target Object
number Becomes 250
Before Modification
ptr ─────► number ─────► 100
After *ptr = 250
ptr ─────► number ─────► 250
Output
250
The Original Object Changes

Assigning through *ptr modifies the object pointed to by ptr. In this example, that object is number.

Program Execution Flow

Program Starts
Create Variable
Variable Receives an Address
Use & to Obtain Address
Store Address in Pointer
Use * to Access Target Object
Read or Modify Object
Program Ends

The pointer workflow involves obtaining an address, storing it in a compatible pointer, and dereferencing the pointer only when it refers to a valid object.

Comparisons

Pointers become easier to understand when compared with ordinary variables and references.

Pointer vs Variable

FeatureVariablePointer
Primary PurposeRepresents an object or valueStores an address
Example Value1000x1000
Direct AccessUse the variable nameUse the pointer value to inspect the address
Indirect Object AccessNot requiredUse dereferencing with *
Can Represent No TargetNot in the pointer senseYes, using nullptr

Reference vs Pointer

FeatureReferencePointer
ConceptAlias for an objectVariable that stores an address
InitializationMust be initializedCan be initialized to an address or nullptr
Null StateA valid reference is expected to refer to an objectCan hold nullptr
ReseatingCannot be reseatedCan store another compatible address later
Access SyntaxNormal variable syntaxDereference with * to access target object
Own Stored ValueReference semanticsStores an address value
Reference Example
int number = 100;
int &ref = number;

ref = 250;
Pointer Example
int number = 100;
int *ptr = &number;

*ptr = 250;
Main Difference

A reference acts as another name for an object. A pointer explicitly stores an address and can be changed to point to another compatible object.

Real-World Applications

Dynamic Memory

Pointers can refer to objects created dynamically during program execution.

Data Structures

Linked lists, trees, and graphs use links between nodes.

Game Development

Pointers can be used in object systems, engines, resource management, and low-level APIs.

Operating Systems

Low-level system programming frequently works with addresses and memory-oriented interfaces.

Hardware Interfaces

Embedded and systems programming may use address-based access to hardware resources.

Legacy and C APIs

Pointers are commonly used when interoperating with C libraries and operating system APIs.

Changing the Pointer Target
int first = 10;
int second = 20;

int *ptr = &first;

ptr = &second;

Unlike a reference, a pointer can later store the address of another compatible object.

Advantages of Pointers

Address-Based Access

Pointers allow programs to store and use object addresses explicitly.

Optional Targets

nullptr can represent that a pointer currently points to no object.

Flexible Targeting

A pointer can be changed to point to another compatible object.

Dynamic Objects

Pointers support direct work with dynamically allocated objects.

Complex Structures

Pointers help connect nodes in linked data structures.

Low-Level Control

Pointers are essential in many systems, embedded, and interoperability scenarios.

  • Store and work with memory addresses.
  • Represent optional object relationships with nullptr.
  • Point to different compatible objects over time.
  • Support dynamic memory techniques.
  • Enable linked data structures.
  • Work with low-level and C-style APIs.
  • Provide indirect access to objects.

Common Beginner Mistakes

Using an Uninitialized Pointer

An uninitialized local pointer has an indeterminate value and must not be dereferenced.

Forgetting the Address-of Operator

A pointer must receive a compatible address, not an ordinary integer value.

Dereferencing nullptr

A null pointer does not point to an object and must not be dereferenced.

Confusing * and &

& obtains an address, while * can access an object through a pointer.

Using a Dangling Pointer

A pointer becomes dangerous when the object it points to no longer exists.

Uninitialized Pointer
// ❌ Dangerous
int *ptr;
std::cout << *ptr;

// ✅ Safe initial state
int *ptr = nullptr;
Forgetting the Address-of Operator
int number = 100;

// ❌ Incorrect
// int *ptr = number;

// ✅ Correct
int *ptr = &number;
Dereferencing nullptr
int *ptr = nullptr;

// ❌ Undefined behavior
// std::cout << *ptr;
Check Before Dereferencing
int *ptr = nullptr;

if (ptr != nullptr)
{
    std::cout << *ptr;
}
Never Dereference an Invalid Pointer

Dereferencing an uninitialized, null, or dangling pointer causes undefined behavior.

Best Practices

  • Initialize pointers when they are declared.
  • Use nullptr when a pointer intentionally has no target.
  • Dereference a pointer only when it refers to a valid object.
  • Check nullable pointers before dereferencing them.
  • Use meaningful names such as studentPtr or currentNode.
  • Prefer references when nullability and reseating are not required.
  • Avoid raw owning pointers in modern C++ when standard resource-management types are more appropriate.
  • Ensure the pointed-to object remains alive while the pointer is used.
  • Avoid returning pointers to local variables.
  • Keep pointer usage as simple and local as possible.
Safe Initialization
int *ptr = nullptr;
Valid Pointer Check
if (ptr != nullptr)
{
    std::cout << *ptr;
}
Point to a Valid Object
int number = 100;
int *ptr = &number;

std::cout << *ptr;
Modern C++ Guideline

Use raw pointers mainly for non-owning relationships and low-level interfaces. For ownership and resource management, modern C++ often uses automatic objects, containers, and smart pointers.

Frequently Asked Questions

What is a pointer?

A pointer is a variable that stores a memory address.

Which operator obtains the address of a variable?

The address-of operator & produces the address of an object.

Which operator accesses an object through a pointer?

The dereference operator * accesses the pointed-to object.

What does int *ptr mean?

It declares ptr as a pointer that can store the address of a compatible int object.

Can a pointer point to another variable later?

Yes. A pointer can be assigned another compatible address.

What is nullptr?

nullptr is the modern C++ null pointer value used to indicate that a pointer currently points to no object.

Can nullptr be dereferenced?

No. Dereferencing a null pointer causes undefined behavior.

What is the difference between ptr and *ptr?

ptr is the address stored in the pointer, while *ptr accesses the object at that address.

What is the difference between a reference and a pointer?

A reference acts as an alias, while a pointer stores an address and can represent no target or point to another compatible object later.

Why are pointers important?

Pointers are important for dynamic memory, linked data structures, optional object relationships, low-level programming, and interoperability with many APIs.

Key Takeaways

  • A pointer is a variable that stores a memory address.
  • The address-of operator & obtains the address of an object.
  • The dereference operator * accesses an object through a pointer.
  • If ptr stores &number, then *ptr accesses number.
  • A pointer has its own storage and can store the address of another object.
  • Pointers can modify pointed-to objects when the type allows modification.
  • Pointers can be changed to point to different compatible objects.
  • nullptr represents a pointer with no current target.
  • Invalid pointers must never be dereferenced.
  • Pointers are important for dynamic memory and linked data structures.
  • Pointers are widely used in low-level programming and C-style APIs.
  • Understanding pointers is essential for advanced C++ programming.

Summary

Pointers are one of the most important low-level features of C++. A pointer stores an address and can provide indirect access to another object.

The address-of operator & obtains the address of an object, while the dereference operator * accesses the object through a valid pointer.

Pointers can be used to read and modify objects, represent optional relationships with nullptr, build linked data structures, work with dynamic memory, and interact with system-level APIs.

Pointers also require careful handling. Uninitialized, null, and dangling pointers must never be dereferenced. Understanding pointer validity and object lifetime is essential for writing safe C++ programs.

With references and pointers understood, you are ready to begin object-oriented programming by learning how C++ classes combine data and behavior into reusable types.

Next Lesson →

Classes