Step 1 of 7 · Reading · ~4 min
Learn
Pointers and Memory
Pointers in Depth: Arrays, Arithmetic and Ranges
In Fundamentals you took an address with &, followed it with *, and passed an int* to change a caller's variable. Here a pointer is a position inside a run of objects. By the end you can write functions over a pointer range, subtract pointers to get a distance, and choose the right const for a pointer.
An array decays to a pointer
Pass an array to a function and it turns into a pointer to its first element, called decay. The length is lost:
std::size_t countOf(int a[]) { return sizeof(a) / sizeof(a[0]); } // a is really int*
int temps[5] = {18, -4, 7, 25, 7};
sizeof(temps) / sizeof(temps[0]) // 5 (20 bytes / 4)
countOf(temps) // 2 (8-byte pointer / 4)
Clang warns sizeof on array function parameter will return size of 'int *'. Pass the end along with the start.
Arithmetic counts elements, not bytes
p + k moves k elements; the compiler scales by sizeof(*p). Subtracting two pointers into the same array gives the element distance, of type std::ptrdiff_t (a signed 8-byte integer here):
const int* p = temps;
*(p + 3) // 25, the same as temps[3]
(p + 3) - temps // 3, not 12
temps[i] is defined as *(temps + i). Pointers into different arrays cannot be meaningfully subtracted or compared.
A range is [first, last)
You know begin()/end() for a vector. A raw array has the same pair: std::begin(temps) is temps, and std::end(temps) is temps + 5, one past the last element. You may form and compare that pointer, never dereference it.
long long sumRange(const int* first, const int* last) {
long long total = 0;
for (const int* p = first; p != last; ++p) total += *p;
return total;
}
sumRange(temps, std::end(temps)) // 53
sumRange(temps, temps) // 0, an empty range is first == last
sumRange(temps + 1, temps + 4) // 28, any slice works
last - first is the element count. A search function reports "absent" with nullptr or with last, the STL way; test for whichever you chose, since *last is out of range.
Four ways to write const
Read the declaration right to left:
const int* p1 = &a; // pointer to const int: p1 = &b is fine, *p1 = 5 is an error
int* const p2 = &a; // const pointer to int: *p2 = 5 is fine, p2 = &b is an error
const int* const p3 = &a; // neither may change
int* p4 = &a; // both may change
Clang reports read-only variable is not assignable for *p1 = 5 and cannot assign to variable 'p2' with const-qualified type 'int *const' for p2 = &b. A function that only reads takes const int*, which accepts const and non-const arrays alike; int* q = constArray; does not compile.
-> reaches a member through a pointer
struct Reading { int celsius; int hour; };
Reading r{21, 14};
Reading* rp = &r;
rp->celsius // 21, shorthand for (*rp).celsius
*rp.celsius does not compile: . binds tighter than *, so it tries rp.celsius first.
Dangling: the storage moved or died
Two cases, both undefined behaviour, so they are described rather than run:
- Stack:
int* f() { int local[3] = {1, 2, 3}; return local; }returns the address of a dead stack frame. Reading it may print old values, garbage, or crash. - Reallocation: with
std::vector<int> v = {1, 2, 3};andint* p = &v[0];, av.push_back(4);grows the capacity from 3 to 6, moves every element to a new buffer and frees the old one.pkeeps the old address. Take the pointer again after any call that can grow the vector.
Common mistakes
>where you need the last tie. For3 9 2 9,*p > *bestkeeps index 1, but the last occurrence is index 3.- Swapping across the whole range. Every pair is swapped twice, so the array comes back unchanged and
1 2 3prints1 2 3. Stop at the middle. - Stopping two converging pointers with
!=. On an even-length range they step past each other and never compare equal, so the loop runs off the array. Use<. - Printing
*pfor a position.p - ais the position;*pis the value stored there.
Your exercise
Write lastMax and reverseRange over a [first, last) range, and compute the position of the maximum by pointer subtraction in main. The starter reads the input and prints the result; the usual bug is picking the first maximum instead of the last.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…