Language-specific · 34
Pointers
Carry around where a value lives (its address) and change the caller's variable.
This lesson is for C++ · C.
Python, JavaScript, TypeScript, Java and Craykon have no pointers that hold raw addresses; objects are reached through references (see passing lists in the functions lesson).
C# allows pointers only inside unsafe code.
A pointer is a variable that holds the memory address of a value instead of the value itself.
The example below swaps two variables by passing their addresses, then takes an array through a pointer to find its sum and its largest element.
#include <iostream> void swapPtr(int* a, int* b) { int t = *a; *a = *b; *b = t;} int sum(const int* p, int n) { // 배열은 첫 칸의 포인터로 넘어와요 int s = 0; for (const int* end = p + n; p < end; ++p) s += *p; return s;} int* findMax(int* p, int n) { if (n == 0) return nullptr; int* best = p; for (int i = 1; i < n; ++i) if (p[i] > *best) best = p + i; return best;} int main() { int a, b, n, arr[100]; std::cin >> a >> b; swapPtr(&a, &b); // 실제 코드라면 std::swap(a, b) std::cout << a << ' ' << b << '\n'; std::cin >> n; for (int i = 0; i < n; ++i) std::cin >> arr[i]; std::cout << sum(arr, n) << '\n'; int* m = findMax(arr, n); if (m != nullptr) std::cout << *m << ' ' << (m - arr) << '\n';}#include <stdio.h> void swap(int *a, int *b) { int t = *a; *a = *b; *b = t;} int sum(const int *p, int n) { /* 배열은 첫 칸의 포인터로 넘어와요 */ int s = 0; for (const int *end = p + n; p < end; p++) s += *p; return s;} int *find_max(int *p, int n) { if (n == 0) return NULL; int *best = p; for (int i = 1; i < n; i++) if (p[i] > *best) best = p + i; return best;} int main(void) { int a, b, n, arr[100]; scanf("%d %d", &a, &b); swap(&a, &b); printf("%d %d\n", a, b); scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", arr + i); printf("%d\n", sum(arr, n)); int *m = find_max(arr, n); if (m != NULL) printf("%d %td\n", *m, m - arr); return 0;}3 8 4 5 1 7 2
8 3 15 7 2
Key points
&xis the address of x, and*p(dereferencing) is the value at the place p points to.
Afterint *p = &x;,*p = 5;meansx = 5;.
You have used addresses ever since passing&ntoscanf.- Passing a number copies it, so changes inside the function don't reach the caller.
To change the caller's variable, pass its address:swap(&a, &b). - An array passed to a function or used in an expression turns into a pointer to its first element (decay).
That's whyp[i]is exactly*(p + i). - Pointer arithmetic:
p + 1points one element ahead (sizeof(int), usually 4 bytes), not one byte.
Subtracting two pointers into the same array (m - arr) gives a count of elements, i.e. the index. - A pointer may point just past the end of an array (
p + n), but you must not read that spot. - A pointer to nothing is NULL.
The example'sfind_maxreturns NULL for zero elements, and the caller checks before reading.
How each language writes it
| C++ | Pointers work as in C; the null pointer is nullptr (since C++11) — to change the caller, a reference void swap(int& a, int& b) is simpler, and in practice you use std::swap(a, b).A reference is an alias that can't be null or be re-pointed, so use pointers only when you really need them |
|---|---|
| C | int *p = &x;, read and write through *p — the null pointer is NULL.A function that changes the caller is void swap(int *a, int *b); one that takes an array also takes its length, like int sum(const int *p, int n) |
Common mistakes
Dereferencing NULL
int *m = find_max(arr, 0);
printf("%d\n", *m);→ Undefined behaviour, usually a crash with Segmentation fault. Nothing tells you where it went wrong, unlike Java's NullPointerException
Check if (m != NULL) before reading *m.
Returning a local variable's address
int *f(void) {
int x = 3;
return &x;
}→ x disappears when the function returns, so the pointer points at a place that no longer exists (a dangling pointer). GCC warns function returns address of local variable; running it prints garbage or crashes
Put the result in an array the caller provides, or in dynamic memory (next lesson).
Measuring a parameter array with sizeof
int count(int arr[]) {
return sizeof(arr) / sizeof(arr[0]);
}→ 8 / 4 = 2 on a 64-bit machine. The parameter int arr[] is really int *arr, so the length is lost (inside main, int arr[5] gives 5)
In C, take the length n separately; in C++, pass a std::vector or std::span (C++20), which carry their length.
Before dereferencing a pointer, always ask whether it points at something that is still alive.
Dereferencing NULL, a local variable of a function that has returned, or a spot outside an array makes C and C++ print garbage or crash, with no error message.
Practice
- A function that reverses ranges8P0062
- Min, max and sum through pointers2P0073
- Walking to the longest run with pointers2P0074
- Name tags pointing at the same list8P0262
- A stock ledger passed by reference1P0085
- Detaching train cars with a pointer to a pointer2P0201
- Fix by reference, find with lower_bound1P0125
- Cloned adventurers and a shared vault3P0159