Step 8 of 10
const and pointers
const can protect two different things when pointers are involved: the data being pointed at, or the pointer itself. Where you put const decides which.
| Declaration | Can change *p? |
Can move p? |
|---|---|---|
const int *p |
no | yes |
int *const p |
yes | no |
const int *const p |
no | no |
The trick is to read the declaration right to left: const int *p is "p is a pointer to an int that is const". int *const p is "p is a const pointer to an int".
Why professionals use it everywhere
When a function takes const int *a, it promises not to change the caller's data, and the compiler enforces the promise. Readers learn from the signature alone that the function only reads. It also allows passing data that genuinely can't change, like string literals.
#include <stdio.h>
#include <stddef.h>
const char *first_upper(const char *s) {
for (; *s != '\0'; s++) {
if (*s >= 'A' && *s <= 'Z') {
return s;
}
}
return NULL;
}
int main(void) {
const char *hit = first_upper("hello World");
if (hit != NULL) {
printf("%s\n", hit);
}
printf("%d\n", first_upper("quiet") == NULL);
return 0;
}
World
1
Returning a pointer into the input
A search can return a pointer to the element it found, instead of an index, and NULL for "not found". If the input was const, the returned pointer should be const too; otherwise the caller could use it to modify data that was promised to be read-only. Returning a const char * as a plain char * makes the compiler warn (discards qualifiers); in C++ it's an outright error.
Note that s++ is allowed above: s is a pointer to const chars, and moving the pointer doesn't change any chars.
Your turn: write const int *find(const int *a, int n, int target) that returns a pointer to the first element equal to target, or NULL if there is none.
Previous: Pointers to pointers Next: Two pointers from both ends