C++: Pointer Basics
Last updated: 2026-08-26
In previous lessons, variables are stored at some location in memory.
But where exactly is that "location"? Can you access it directly?
Pointers are variables that store addresses — they let you manipulate memory directly.
1. What is a Pointer?
(1) 1.1 Pointers in Everyday Life
| Real-life Analogy | Program Equivalent |
|---|---|
| Your home address (e.g., "123 Main Street...") | Pointer (stores an address) |
| Your actual house (the building the address points to) | Variable (the memory space the address points to) |
Essence of a pointer: A variable that stores an address.
(2) 1.2 Why Do We Need Pointers?
- Dynamic memory allocation (covered later with
new/delete) - Functions need to modify external variables (pass pointers to functions)
- Working with arrays (array names are pointers)
- Implementing complex data structures (linked lists, trees, graphs)
2. Pointer Declaration and Initialization
(1) 2.1 Declaring a Pointer
Syntax:
▶ Example 2: Code Example (Difficulty ⭐)
Type* pointerName;
Output:
(Program output)
Example:
#include <iostream>
int main() {
int* pInt; // pointer to int
double* pDouble; // pointer to double
char* pChar; // pointer to char
return 0;
}
💡 Key point: Type* means "a pointer to that type."
(2) 2.2 Address-of Operator (&)
& is used to get a variable's address.
#include <iostream>
int main() {
int x = 5;
std::cout << "x 's value: " << x << std::endl;
std::cout << "x 's address: " << &x << std::endl; // Output similar to 0x7ffd4a3b
return 0;
}
Output (example):
x 's value: 5
x 's address: 0x7ffd4a3b
💡 Tip: The specific format of addresses depends on the system and compiler.
(3) 2.3 Initializing a Pointer
#include <iostream>
int main() {
int x = 5;
int* p = &x; // p points to x(p stores x's address)
std::cout << "x 's address: " << &x << std::endl;
std::cout << "p 's value: " << p << std::endl; // same as &x
return 0;
}
3. Dereferencing
(1) 3.1 Dereference Operator (*)
* is used to access the value a pointer points to.
#include <iostream>
int main() {
int x = 5;
int* p = &x; // p points to x
std::cout << "x = " << x << std::endl; // 5
std::cout << "*p = " << *p << std::endl; // 5(Dereference)
return 0;
}
💡 Key point: *p is essentially x!
(2) 3.2 Modifying a Variable Through a Pointer
#include <iostream>
int main() {
int x = 5;
int* p = &x;
std::cout << "Before: x = " << x << std::endl; // 5
*p = 100; // Modify x's value via pointer
std::cout << "After: x = " << x << std::endl; // 100
return 0;
}
4. Size of Pointers
(1) 4.1 sizeof a Pointer
#include <iostream>
int main() {
int* pInt;
double* pDouble;
char* pChar;
std::cout << "int* size: " << sizeof(pInt) << " bytes" << std::endl;
std::cout << "double* size: " << sizeof(pDouble) << " bytes" << std::endl;
std::cout << "char* size: " << sizeof(pChar) << " bytes" << std::endl;
return 0;
}
Output (64-bit system):
int* size: 8 bytes
double* size: 8 bytes
char* size: 8 bytes
💡 Key point: All pointers are the same size (8 bytes on 64-bit systems, 4 bytes on 32-bit systems) — because they all store addresses.
5. Null Pointers (nullptr)
(1) 5.1 What is a Null Pointer?
A null pointer is a pointer that doesn't point to any object.
#include <iostream>
int main() {
int* p = nullptr; // Null pointer (recommended since C++11)
if (p == nullptr) {
std::cout << "p is null pointer" << std::endl;
}
return 0;
}
💡 Tip: Before C++11, NULL was used (which is essentially 0), but nullptr is now recommended.
(2) 5.2 Dereferencing a Null Pointer Causes a Crash
#include <iostream>
int main() {
int* p = nullptr;
std::cout << *p << std::endl; // ❌ Undefined behavior! May crash
return 0;
}
Running result:
Segmentation fault (core dumped) // Linux
Or
Process finished with exit code -1073741819 // Windows
⚠️ Never dereference a null pointer!
6. Pointers as Function Parameters
(1) 6.1 The Problem: Functions Need to Modify External Variables
#include <iostream>
void modifyValue(int x) {
x = 100; // ❌ modifying a copy, does not affect original variable
}
int main() {
int a = 5;
modifyValue(a);
std::cout << "a = " << a << std::endl; // 5(Unchanged)
return 0;
}
(2) 6.2 Solution: Pass a Pointer
#include <iostream>
void modifyValue(int* p) {
*p = 100; // ✅ modify original variable via pointer
}
int main() {
int a = 5;
modifyValue(&a); // Pass address
std::cout << "a = " << a << std::endl; // 100(Changed!)
return 0;
}
7. Practice: Swapping Two Variables
▶ Example 1: Implementing swap with Pointers (Difficulty ⭐)
#include <iostream>
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 3, y = 5;
std::cout << "Before swap: x = " << x << ", y = " << y << std::endl;
swap(&x, &y); // Pass address
std::cout << "After swap: x = " << x << ", y = " << y << std::endl;
return 0;
}
Output:
Before swap: x = 3, y = 5
After swap: x = 5, y = 3
💡 Tip: Later you'll learn references — implementing swap with references is even simpler.
8. Common Errors
(1) 8.1 Dereferencing an Uninitialized Pointer
#include <iostream>
int main() {
int* p; // ❌ Uninitialized (wild pointer)
std::cout << *p << std::endl; // ❌ Undefined behavior!
return 0;
}
Fix: Initialize to nullptr, or point to an existing variable.
(2) 8.2 Pointer Type Mismatch
#include <iostream>
int main() {
int x = 5;
double* p = &x; // ❌ Error: int* Cannot point to int
return 0;
}
Compiler error message:
error: cannot convert 'int*' to 'double*' in initialization
▶ Example 3: Pointers and Arrays (Difficulty ⭐)
#include <iostream>
int main() {
int arr[] = {10, 20, 30, 40, 50};
int* p = arr; // array name is the first element address
for (int i = 0; i < 5; i++) {
std::cout << "arr[" << i << "] = " << *(p + i) << std::endl;
}
return 0;
}
Output:
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
arr[4] = 50
arr is the address of the first element, equivalent to &arr[0]. When traversing an array with a pointer, *(p + i) is equivalent to p[i] or arr[i].
❓ FAQ
nullptr; references must be initialized > - Pointers can be reassigned to point to other variables; references cannot be rebound once bound > - Pointers need *p to dereference; references use the variable name directly📖 Summary
- Pointers are variables that store addresses
- Declaration:
Type* pointerName; - Get address:
&variableName - Dereference:
*pointerName - Null pointer:
nullptr - Never dereference a null pointer or a wild pointer
📝 Exercises
-
Basic (Difficulty ⭐): Declare an
intvariablex = 10, then declare anint*pointerppointing tox. Output the value ofxand*p. -
Intermediate (Difficulty ⭐⭐): Write a function
void addTen(int* p)that adds 10 to the variable pointed to by the pointer. Test it inmain. -
Challenge (Difficulty ⭐⭐⭐): Write a program that declares three
intvariablesa, b, c, and three pointers pointing to each of them. Use the pointers to change all three variables to 100, then output them.
- Pointers are variables that store memory addresses
- & gets the address, * dereferences to access the pointed-to value
- Declaration: Type* pointerName (e.g., int* p;)
- Null pointer nullptr (C++11) replaces NULL
- Pointers pointing to the same memory — changing one affects the other
13. 🚀 Next Step
Now that you've learned pointer basics, let's move on to Pointers and Arrays (Lesson 23) — understanding that array names are pointers, and pointer arithmetic.