Pointers Fundamentals
Imagine you want to visit your friend's house.
You don't pick up their entire house and carry it with you, right? That would be impossible!
Instead, you simply carry something much lighter and more useful: their address.
Using this address, you can easily find and visit their house whenever you want, without moving the entire structure.
In the world of C++, a pointer works exactly like that address.
Instead of carrying around a big, heavy object — like a large number, a long text (string), or even a big piece of data — we just carry the address where that object lives inside the computer’s memory.
With the help of this address (the pointer), we can find, access, and even modify the actual object whenever we need to.
This clever trick makes our programs faster, lighter, and smarter, because we’re not wasting time and resources moving around large chunks of data unnecessarily.
Instead, we’re just handling their location in memory — making everything more efficient!
Today, we’re about to dive into this exciting and powerful world of pointers.
Ready? Let’s go explore!
What is a Pointer?
Just like a house address tells you where the house is,
a pointer tells you where a variable is stored inside your computer.
In simple words, a pointer is a variable that stores the memory address of another variable.
Formal Definition:
A pointer is a special variable that stores the memory address of another variable.
- It points to the location where the data lives.
- It helps in accessing, modifying, and sharing data efficiently.
Example:
int num = 25; // normal variable holding a value
int* p = # // pointer holding the address of num
- num holds 25.
- p holds the address where 25 is stored.
So, whenever you think of pointers,
just imagine carrying a map to your friend's house — not the entire house!
Pointer initialization and Declaration
Imagine you just made a new friend.
Before you save their phone number in your phone, what do you do?
- First, you create a contact name (like "Rahul New Friend").
- Then, you save their number under that name.
Similarly, in C++:
- First, we declare a pointer (like giving it a name).
- Then, we initialize it (give it an actual memory address).
Pointer Declaration
Declaration means telling the computer:
"Hey, I am creating a pointer that will hold the address of a specific type of data."
Syntax:
dataType* pointerName;
- dataType ➔ Type of data the pointer will point to (like int, char, float, etc.).
- * ➔ Tells C++ "this is a pointer!"
- pointerName ➔ Any name you choose for your pointer (like you name a variable).
Example:
int* ptr; // Pointer to an integer
char* cptr; // Pointer to a character
float* fptr; // Pointer to a float
- int* ptr; ➔ ptr can store the address of an integer.
- char* cptr;➔ cptr can store the address of a character.
- float* fptr; ➔ fptr can hold the address of a float.
Important:
The * can also be written close to the variable name (like int *ptr;) — both ways are fine.
Most people prefer attaching * to the variable type to show that it's a pointer.
Pointer Initialization
Initialization means telling the computer:
"Not only am I creating the pointer, but I’m also giving it an actual address to store right away!"
We usually do this using the address-of operator (&).
Example:
int num = 10; // A normal integer variable
int* ptr = # // Pointer initialized with the address of num
- &num ➔ Gives the address of num.
- ptr now holds the address of num.
Here's what's happening:
Step | What's Happening | Example |
---|---|---|
1 | Create a normal variable | int num = 10; |
2 | Declare a pointer | int* ptr; |
3 | Initialize the pointer with address | ptr = # |
OR you can do steps 2 and 3 together, like:
int* ptr = #
Important Notes:
- You must initialize pointers before using them.
Otherwise, they might point to random memory and crash your program. - If you don't have a valid address yet, you can initialize with
nullptr
(a special value that means "no address"):
int* ptr = nullptr;
In Short:
Declaration = Naming your pointer (like creating a contact).
Initialization = Giving it a real address (like saving your friend’s number).
Address-of (&) and Dereference (*) Operators
Imagine you want to visit your friend’s house.
- First, you need their house address (to find where they live).
- Second, when you reach there, you need a key to open the door and get inside.
In C++:
- The address-of operator & gives you the address of a variable (like your friend’s house address).
- The dereference operator * lets you go inside that address and get the actual value (like using the key to enter the house).
Both are needed when you work with pointers!
1. Address-of Operator (&)
What is it?
The & symbol is used to find the memory address of a variable.
It answers the question:
"Where does this variable live in memory?"
Syntax:
&variableName
Example:
#include<iostream>
using namespace std;
int main() {
int num = 10;
cout << "Value of num: " << num << endl;
cout << "Address of num: " << &num << endl;
return 0;
}
Output:
Value of num: 10
Address of num: 0x61fe14
(You will see a different memory address like 0x61fe14 — that’s normal!)
In Simple Words:
- num ➔ value = 10
- &num ➔ address = where 10 is stored
Just like you know your friend’s name and their home address!
2. Dereference Operator (*)
What is it?
The * symbol is used to get the value stored at an address.
It answers the question:
"What is inside the house at this address?"
Syntax:
*pointerName
Example:
#include<iostream>
using namespace std;
int main() {
int num = 10;
int* ptr = # // ptr now holds address of num
cout << "Address stored in ptr: " << ptr << endl;
cout << "Value at address stored in ptr: " << *ptr << endl;
return 0;
}
Output:
Address stored in ptr: 0x61fe14
Value at address stored in ptr: 10
In Simple Words:
- ptr ➔ holds address.
- *ptr ➔ gives value at that address.
Just like you reach your friend’s house using the address, and then enjoy a delicious cake inside!
Quick Table to Remember:
Operator | Symbol | Meaning | Example |
---|---|---|---|
Address-of | & | Gets the address of a variable | &num |
Dereference | * | Gets the value at a memory address | *ptr |
Important Tip:
When you use * during pointer declaration like int* ptr;, it means "this variable is a pointer."
When you use * during value access like *ptr, it means "go to the address and fetch the value."
Same symbol, but different jobs based on context!
Null Pointers in C++
Imagine you go to a big parking lot looking for your car.
Some spots have cars parked in them, but some spots are empty.
If someone asks you, "Hey, which car is parked in spot 17?"
And spot 17 is empty, you’d say, "There’s no car here!"
In C++:
- A normal pointer points to a valid memory address (like a spot with a car).
- A null pointer means the pointer does not point to any valid memory location (like an empty parking spot).
What is a Null Pointer?
A null pointer is a pointer that doesn't point to any variable or memory location.
It is specially used to show that the pointer is empty or unassigned.
Think of it like this:
“I have a pointer, but right now it points to nothing.”
How to Create a Null Pointer?
We can assign a nullptr to a pointer when we don't want it to point anywhere.
Syntax:
int* ptr = nullptr;
Here:
- ptr is a pointer.
- nullptr is a special keyword in C++ that means "no address".
Example:
#include<iostream>
using namespace std;
int main() {
int* p = nullptr; // p is a null pointer
if(p == nullptr) {
cout << "Pointer is null. It doesn't point to anything!" << endl;
}
else {
cout << "Pointer points to something." << endl;
}
return 0;
}
Output:
Pointer is null. It doesn't point to anything!
Why Do We Use Null Pointers?
- To safely indicate that a pointer is not assigned yet.
- To avoid bugs by checking if a pointer is valid before using it.
- To initialize pointers properly and not leave them pointing to random memory (called "dangling pointers").
Important Tip: Always Initialize Your Pointers!
If you don't know where to point yet, initialize your pointer to nullptr.
Bad:
int* p; // Dangerous! p has garbage value.
Good:
int* p = nullptr; // Safe! p is null.
This way, before using the pointer, you can check:
if(p != nullptr) {
// Safe to use p
}
Quick Summary:
Term | Meaning | Example |
---|---|---|
Normal Pointer | Points to a valid address | int* p = # |
Null Pointer | Points to nothing | int* p = nullptr; |
In Short:
A normal pointer is like parking your car in a spot.
A null pointer is like an empty parking spot — no car is there!
Pointers Fundamentals in C++ Try on Compiler
#include<iostream>
using namespace std;
int main() {
// --------- Definition of Pointers ---------
// A pointer is a variable that holds the address of another variable.
// --------- Pointer Declaration and Initialization ---------
int num = 10; // normal integer variable
int* ptr = # // pointer declared and initialized with the address of num
// --------- Address-of Operator (&) ---------
// &num gives the memory address of num
cout << "Address of num (using & operator): " << &num << endl;
// --------- Dereference Operator (*) ---------
// *ptr gives the value stored at the address held by ptr
cout << "Value at address stored in ptr (using * operator): " << *ptr << endl;
// Printing both to clearly show the connection
cout << "Address stored in ptr: " << ptr << endl;
cout << "Accessing value through pointer (dereferencing ptr): " << *ptr << endl;
// --------- Null Pointers ---------
// Creating a null pointer (points to nothing)
int* nullPtr = nullptr;
// Checking if pointer is null
if (nullPtr == nullptr) {
cout << "nullPtr is a null pointer. It doesn't point to any memory location." << endl;
}
return 0;
}
Time Complexity: O(1)
The time complexity of this code is O(1) (constant time).
This is because all operations — like declaring variables, assigning addresses, printing values, and checking if a pointer is nullptr — are simple, direct operations that take a fixed amount of time. There are no loops, no recursion, and no operations that depend on the size of input.
Space Complexity: O(1)
The space complexity is also O(1) (constant space).
The program only uses a few basic variables: one integer (num) and two pointers (ptr and nullPtr). These occupy a small, fixed amount of memory, regardless of any input size. No additional memory or dynamic allocation (like arrays, vectors, or heap memory) is involved.