Paramclasses Academy - Blog

Tutorials Details

What is Pointers in C++

What is Pointers in C++

October 15, 2026

Pointers are one of the most important concepts in C++. They let you work with memory addresses, access objects indirectly, modify variables through functions, and understand how dynamic memory works.

In this module, we’ll learn pointers step by step, with code examples, expected output, exercises, and a quiz.

1. Learning objectives

By the end of this module, you will be able to:

  • Understand memory addresses and pointers.

  • Declare and initialize pointer variables.

  • Use & (address-of) and * (dereference).

  • Work safely with null pointers.

  • Use pointers with arrays and functions.

  • Recognize common pointer errors.

Estimated time

60–90 minutes

Prerequisites

Variables, data types, arrays, loops, and functions

2. What is a pointer?

A normal variable stores a value. A pointer stores the memory address of an object.

For example:

int number = 25;
int* ptr = &number;

Here:

  • number stores the value 25.

  • &number means “the address of number.”

  • ptr stores that address.

  • int* means “pointer to an int.”

Think of a variable as a box containing a value. A pointer is like a note telling you where that box is located.

3. Understanding & and *

These two operators are central to pointers, but their meanings depend on how they are used.

&

Address-of operator

&number gives the memory address of number.

*

Dereference operator

*ptr accesses the object that ptr points to.

Example 1: A basic pointer


#include <iostream>
using namespace std;

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

    cout << "Value: " << number << endl;
    cout << "Address: " << &number << endl;
    cout << "Pointer stores: " << ptr << endl;
    cout << "Value through pointer: " << *ptr << endl;

    return 0;
}

Sample output (the address will vary):

Value: 25
Address: 0x7ffd1234
Pointer stores: 0x7ffd1234
Value through pointer: 25

The address shown is only an example. Your program will likely display a different address.

Notice that ptr and &number display the same address, while *ptr gives the value stored at that address.

4. How a pointer works in memory

Consider this code:

int number = 25;
int* ptr = &number;

The relationship is:

Variable: number

25

Contains the integer value

Pointer: ptr

Address of number

Stores where the integer is located

Dereferencing ptr with *ptr accesses the value 25.

A pointer has its own storage too: the pointer variable stores an address, rather than storing the pointed-to integer itself.

5. Declaring and initializing pointers

Syntax

data_type* pointer_name;

Examples:

int* intPtr;
double* doublePtr;
char* charPtr;

The pointer type matters: int* points to an int, while double* points to a double.

Declare and initialize a pointer before dereferencing it:

int score = 90;
int* scorePtr = &score;

You can write the spacing in different ways:

int* ptr;
int *ptr;
int * ptr;

All three are valid C++ declarations. The first style is common.

Important: An uninitialized local pointer contains an indeterminate value. Do not dereference it or assume it points to a valid object.

6. Modifying a variable through a pointer

A pointer doesn’t just let you read a value. You can also change the value of the object it points to by assigning through *ptr.

Example 2: Change a value using a pointer


#include <iostream>
using namespace std;

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

    cout << "Before: " << number << endl;

    *ptr = 50;

    cout << "After: " << number << endl;

    return 0;
}

Output

Before: 10
After: 50

Why did number change? Because ptr points to number, so *ptr = 50; updates the original variable.

7. Null pointers

A pointer should point to a valid object before you dereference it. If it currently points to nothing, use a null pointer.

int* ptr = nullptr;

nullptr is the modern C++ way to represent a pointer that does not point to an object.

Example 3: Check before dereferencing


#include <iostream>
using namespace std;

int main() {
    int* ptr = nullptr;

    if (ptr != nullptr) {
        cout << *ptr << endl;
    } else {
        cout << "Pointer is null." << endl;
    }

    return 0;
}

Output

Pointer is null.

Never dereference a null pointer:

int* ptr = nullptr;
// cout << *ptr;  // Undefined behavior

A null check is useful, but it does not prove that every non-null pointer is valid. A dangling pointer can be non-null and still be unsafe to dereference.

8. Pointers and arrays

Arrays and pointers are closely related in C++. In many expressions, an array name converts to a pointer to its first element. However, an array is not itself a pointer.

Example 4: Access array elements using a pointer


#include <iostream>
using namespace std;

int main() {
    int numbers[] = {10, 20, 30, 40, 50};
    int* ptr = numbers;

    for (int i = 0; i < 5; i++) {
        cout << *(ptr + i) << " ";
    }

    cout << endl;
    return 0;
}

Output

10 20 30 40 50

Explanation:

  • numbers converts to a pointer to numbers[0] in this initialization.

  • ptr + 1 points to the next integer element, not simply the next byte.

  • *(ptr + i) accesses the element at index i.

These expressions are equivalent for valid array indices:

Array notation

Pointer notation

numbers[0]

*(numbers + 0)

numbers[1]

*(numbers + 1)

numbers[2]

*(numbers + 2)

Example 5: Update array values using a pointer


#include <iostream>
using namespace std;

int main() {
    int numbers[] = {1, 2, 3};
    int* ptr = numbers;

    *(ptr + 1) = 99;

    for (int i = 0; i < 3; i++) {
        cout << numbers[i] << " ";
    }

    return 0;
}

Output

1 99 3

The second element changed because *(ptr + 1) refers to numbers[1].

Safety rule: Pointer arithmetic is valid only within an array’s bounds, or one position past its end for limited purposes such as comparisons. The one-past pointer must not be dereferenced.

9. Passing pointers to functions

A function can receive a pointer as a parameter. This lets it access or modify an object supplied by the caller.

Example 6: Modify a variable inside a function


#include <iostream>
using namespace std;

void updateValue(int* ptr) {
    if (ptr != nullptr) {
        *ptr = 100;
    }
}

int main() {
    int number = 20;

    updateValue(&number);

    cout << number << endl;

    return 0;
}

Output

100

How it works:

  1. &number passes the address of number.

  2. The parameter ptr receives that address.

  3. *ptr = 100; updates the original variable.

For a simple function that modifies a required variable, a reference parameter (int&) is often easier and safer to use. Pointer parameters are useful when an object may be absent (nullptr) or when pointer semantics are specifically needed.

10. Pointers vs. references

Both pointers and references can provide indirect access to an object, but they behave differently.

Feature

Pointer

Reference

Declaration

int* p = &x;

int& r = x;

Can represent no object?

Yes, using nullptr

No, a valid reference must be initialized

Can be redirected?

Yes, by assigning another address

No, it remains bound to its original object

Access value

*p

r

Typical use

Optional objects, pointer-based data structures

Aliases and function parameters

Example 7: Compare the syntax


#include <iostream>
using namespace std;

int main() {
    int x = 10;

    int* p = &x;
    int& r = x;

    *p = 20;
    cout << x << endl;

    r = 30;
    cout << x << endl;

    return 0;
}

Output

20
30

Both forms update x, but they use different syntax and have different rules.

11. Dynamic memory: new and delete

C++ allows you to request memory dynamically. For learning purposes, here is the basic pointer pattern:

int* ptr = new int(42);

cout << *ptr << endl;

delete ptr;
ptr = nullptr;

Output

42
  • new int(42) creates an integer with value 42 and returns a pointer to it.

  • delete ptr releases that dynamically allocated integer.

  • ptr = nullptr makes the pointer visibly empty afterward; it does not release memory by itself.

After delete, do not dereference the old pointer. Any other pointer that still refers to the released object is also unsafe to use.

For arrays allocated with new[], the matching operation is delete[]. Mismatching new/delete and new[]/delete[] causes undefined behavior.

Prefer modern C++ ownership tools

In real projects, prefer standard library containers and smart pointers over manually managing memory whenever possible:

  • Use std::vector<int> for a dynamic array of integers.

  • Use std::unique_ptr<T> for exclusive ownership of a dynamically allocated object.

  • Use std::shared_ptr<T> only when shared ownership is actually needed.

For example, a vector manages its own storage:


#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> numbers = {10, 20, 30};
    numbers.push_back(40);

    for (int value : numbers) {
        cout << value << " ";
    }

    return 0;
}

Output

10 20 30 40

You do not need new or delete here; vector handles its storage automatically.

12. Common pointer mistakes

Learn these carefully. Pointer bugs can cause crashes or unpredictable behavior.

Mistake 1: Dereferencing an uninitialized pointer

int* ptr;
// cout << *ptr;  // Undefined behavior

Fix: Initialize it to a valid address or nullptr.

Mistake 2: Dereferencing nullptr

int* ptr = nullptr;
// *ptr = 10;  // Undefined behavior

Fix: Check that the pointer refers to a valid object before using it.

Mistake 3: Returning a pointer to a local variable

int* getValue() {
    int x = 10;
    return &x;  // Wrong
}

Fix: Do not return the address of a local variable that stops existing when the function returns. Return a value, or use an appropriate lifetime-managed object.

Mistake 4: Using memory after releasing it

int* ptr = new int(10);
delete ptr;
// cout << *ptr;  // Wrong

Fix: Never access the released object. Set ptr = nullptr after deletion if that helps prevent accidental reuse of that pointer.

Mistake 5: Accessing beyond array bounds

int values[] = {10, 20, 30};
int* ptr = values;
// cout << *(ptr + 3);  // Wrong

Fix: Valid element indices are 0, 1, and 2.

13. Mini project — Pointer-based array analyzer

Build a program that calculates the sum and average of an array using a pointer.


#include <iostream>
using namespace std;

int main() {
    int numbers[] = {10, 20, 30, 40, 50};
    int size = 5;
    int* ptr = numbers;
    int sum = 0;

    for (int i = 0; i < size; i++) {
        sum += *(ptr + i);
    }

    double average = static_cast<double>(sum) / size;

    cout << "Array elements: ";
    for (int i = 0; i < size; i++) {
        cout << *(ptr + i) << " ";
    }

    cout << "\nSum: " << sum << endl;
    cout << "Average: " << average << endl;

    return 0;
}

Expected output

Array elements: 10 20 30 40 50
Sum: 150
Average: 30

How the project works

  1. ptr points to the first element of numbers.

  2. The loop uses *(ptr + i) to read each element.

  3. sum accumulates the elements.

  4. static_cast<double>(sum) ensures the average calculation uses floating-point division.

Project challenges

After the program works, improve it:

  • Calculate the largest element using a pointer.

  • Calculate the smallest element.

  • Count how many elements are greater than 25.

  • Modify each element by multiplying it by 2.

14. Hands-on exercises

Try solving these without looking at the solutions first.

Exercise 1 — Basic pointer

Declare an integer with value 75, create a pointer to it, and print the value using the pointer.

Hint: Use int* and *ptr.

Exercise 2 — Change a value

Create an integer with value 5. Use a pointer to change it to 99. Print the original variable.

Hint: Assign through the dereferenced pointer.

Exercise 3 — Traverse an array

Given int arr[] = {3, 6, 9, 12};, print all four elements using pointer arithmetic.

Hint: Use *(ptr + i) inside a loop.

Exercise 4 — Function with a pointer

Write a function named doubleValue that accepts an int* and doubles the pointed-to integer. Call it from main().

Hint: Check for nullptr before modifying the value.

Exercise 5 — Debug the code

Identify the problem and fix this program.

int number = 10;
int* ptr = nullptr;
*ptr = number;

Hint: The pointer must point to a valid integer before you dereference it.

Want to check your work? Select below to reveal the solutions.

Show exercise solutions

15. Interactive knowledge-check quiz

Choose one answer for each question, then submit to see your score.

Module 9 quiz

0 / 8 answered

1. What does a pointer store?

The value of every variable

The memory address of an object

Only an integer value

2. What does &number mean in an expression?

The value of number

The size of number

The address of number

3. What does *ptr do when ptr is valid?

Accesses the pointed-to object

Deletes the pointer

Creates a new pointer

4. Which is the modern null pointer value in C++?

0.0

nullptr

empty

5. If ptr points to x, what does *ptr = 50 do?

Changes x to 50

Changes ptr into an integer

Prints the address of x

6. For int arr[3] = {1, 2, 3}; which pointer expression accesses the second element?

*(arr + 1)

*(arr + 3)

*arr + 3

7. What is wrong with dereferencing a null pointer?

It always prints zero

It causes a compile-time error in every case

It results in undefined behavior

8. Which is generally preferred for a growable array in modern C++?

std::vector

An uninitialized pointer

A pointer to a local variable

Submit quiz

16. Module 9 completion checklist

Your progress

0 of 8

Explain what a pointer stores.

Use & to obtain an address and * to dereference a pointer.

Initialize pointers safely and understand nullptr.

Read and update array elements using pointer arithmetic.

Pass pointers to functions.

Explain the difference between pointers and references.

Recognize dangling pointers and invalid memory access.

Complete the pointer-based array analyzer.