Const Correctness
Promising not to change what you only read.
6 minute read
Big idea
const is a promise: "I won't change this." Put it on pointer parameters a function only reads, and the compiler holds the function to that promise.
Recap: const on a plain variable
You met const in Constants and Keywords:
const int LIMIT = 10;
LIMIT = 11; // ✗ error: read-only
That's simple. Pointers make it more interesting, because there are two things that could be read-only: the data the pointer leads to, and the pointer itself.
Reading the declarations
Read pointer declarations right to left:
| Declaration | Read it as | *p = 5; | p = &other; |
|---|---|---|---|
int *p | p is a pointer to int | ✓ | ✓ |
const int *p | p is a pointer to an int that's const | ✗ | ✓ |
int *const p | p is a const pointer to int | ✓ | ✗ |
const int *const p | a const pointer to a const int | ✗ | ✗ |
The second line is the one you'll write all the time. (int const *p means exactly the same as const int *p.)
const parameters: "I only look"
When a function takes an array or string just to read it, mark it const:
#include <stdio.h>
int sum(const int *a, int n) {
int total = 0;
for (int i = 0; i < n; i++) {
total += a[i];
}
return total;
}
int count_char(const char *s, char c) {
int n = 0;
for (int i = 0; s[i] != '\0'; i++) {
if (s[i] == c) n++;
}
return n;
}
int main(void) {
int marks[] = {70, 85, 90};
printf("%d\n", sum(marks, 3));
printf("%d\n", count_char("banana", 'a'));
return 0;
}output
245
3Run and edit it in the app.
Two wins:
- Readers know at a glance that
sumwon't changemarks— no need to read its body. - The compiler checks. If
sumtriesa[0] = 0;, it's a compile error, not a bug found next week.
The standard library does this everywhere: size_t strlen(const char *s); — strlen promises not to change your string. char *strcpy(char *dest, const char *src); — it writes dest, only reads src.
The compiler catches it
#include <stdio.h>
void shout(const char *s) {
for (int i = 0; s[i] != '\0'; i++) {
if (s[i] >= 'a' && s[i] <= 'z') {
s[i] = s[i] - 'a' + 'A';
}
}
}
int main(void) {
char word[] = "hello";
shout(word);
printf("%s\n", word);
return 0;
}output
HELLORun and edit it in the app.
shout does change the string, so it must not promise otherwise — remove const from its parameter. const should tell the truth.
Watch it
String literals are read-only
A string literal like "hello" lives in read-only memory. Point at it with const char *:
const char *name = "Asha"; // ✓ honest
char *name2 = "Asha"; // compiles, but name2[0] = 'a' may crash
char name3[] = "Asha"; // ✓ an array COPY you're allowed to change
Given const char *p = buffer; which line is a compile error?
Common mistake
Casting const away to silence the compiler: ((char *) s)[0] = 'X';. It compiles — and if s points to a literal, the program may crash. If you need to change it, don't take it as const.
Think of it like
Lending someone a book with "reference only — no notes" stamped inside. They can read every page, flip back and forth (move the pointer), but not write in it. And if they try, the librarian (compiler) stops them at the desk.
Key terms
const— Marks something read-only.- Pointer to const (
const int *p) — Can't change the data throughp;pitself can move. - Const pointer (
int *const p) —pcan't move; the data can change. - Const correctness — Marking everything that shouldn't change as
const, so the compiler enforces it.
Check yourself
Given const int *p; what can't you do?
Why does strlen take a const char *?
How should you point at the string literal "hello"?