Question
What is the difference between these two declarations in C or C++?
char * const pointer;
const char *pointer;
Specifically, which part is constant in each declaration: the pointer itself or the character data it points to?
Short Answer
By the end of this page, you will be able to read const in pointer declarations, determine whether a pointer can be reassigned or whether its pointed-to data can be changed, and choose the appropriate declaration for function parameters and variables.
Concept
const means that something cannot be modified through that name or expression. With pointers, there are two possible things that can be constant:
- The pointed-to value — the character data.
- The pointer variable — the memory address stored in the pointer.
A pointer declaration has both parts:
char *pointer;
chardescribes the data at the address.pointerstores the address.
The location of const tells you what is protected.
const char *pointer;
The characters are read-only through pointer, but the pointer may later store a different address.
char * const pointer = buffer;
The pointer must keep the same address after initialization, but the characters in the buffer may be changed.
This distinction matters because APIs often need to express intent. A function that only reads text should accept const char *, preventing accidental edits to its input. A pointer that must always refer to one specific buffer can be declared char * const.
Mental Model
Think of a pointer as a sticky note containing a house address, and the characters as the items inside the house.
const char *means: you may move the sticky note to another house, but you are not allowed to change items in the current house through this note.char * constmeans: the sticky note must keep the same address, but you may change items in that house.const char * constmeans: the note cannot move, and the items cannot be changed through it.
Syntax and Examples
The easiest reading rule is: start at the variable name and move outward.
char * const fixed_pointer = buffer;
fixed_pointer is a const pointer to char. Its address cannot change.
char buffer[] = "cat";
char other[] = "dog";
char * const fixed_pointer = buffer;
fixed_pointer[0] = 'C'; // Valid: changes buffer to "Cat"
// fixed_pointer = other; // Error: fixed_pointer itself is const
const char *read_only_pointer = "cat";
read_only_pointer is a pointer to const char. The pointer may change, but modifying a character through it is forbidden.
const char *read_only_pointer = "cat";
const char *other = "dog";
read_only_pointer = other; // Valid: pointer now refers to "dog"
// read_only_pointer[0] = 'C'; // Error: pointed-to char is const
You can make both parts constant:
const char * const fixed_read_only_pointer = "cat";
// fixed_read_only_pointer = "dog"; // Error
// fixed_read_only_pointer[0] = 'C'; // Error
In C, const char * and char const * mean exactly the same thing. Many developers prefer const char * because it reads naturally as “pointer to constant characters.”
Step by Step Execution
Consider this C example:
#include <stdio.h>
int main(void) {
char name[] = "Ada";
char city[] = "Rome";
char * const current_name = name;
const char *label = "Name";
current_name[0] = 'E';
label = city;
printf("%s: %s\n", label, current_name);
return 0;
}
Step by step:
nameis a writable character array containing"Ada".cityis another writable character array containing"Rome".current_nameis initialized with the address ofname. Its address is now fixed because the pointer isconst.labelinitially points to the string literal"Name". Its pointed-to characters areconstthroughlabel.current_name[0] = 'E'is valid becausecurrent_namepoints to writable characters.namebecomes"Eda".label = cityis valid becauselabelitself is not constant; it can point elsewhere.- The program prints:
Rome: Eda
The code could not reassign current_name, and it could not modify characters through label.
Real World Use Cases
-
Read-only text parameters: Functions that inspect text without editing it should use
const char *.size_t text_length(const char *text); -
String literals: A string literal should be treated as read-only. In C++, assigning one to
char *is invalid; useconst char *.const char *message = "File not found"; -
Fixed output buffer pointer: Within a function,
char * constcan state that the function will write into one selected buffer and should not redirect the pointer.void make_uppercase(char * const buffer); -
Embedded and systems code: A pointer to memory-mapped data may be fixed, while access to the data is controlled separately. Qualifiers communicate those constraints.
-
Library interfaces:
consthelps callers and maintainers understand whether a function might alter their data.
Real Codebase Usage
In production code, const char * is much more common than char * const in public function declarations because read-only input is a frequent requirement.
Read-only function input
#include <stdio.h>
void print_status(const char *message) {
if (message == NULL) {
return;
}
puts(message);
}
The const contract says print_status will not change the caller's text through message.
Mutable buffer with validation
#include <ctype.h>
#include <stddef.h>
void uppercase_ascii(char *text) {
if (text == NULL) {
return;
}
for (size_t i = 0; text[i] != '\0'; i++) {
text[i] = (char)toupper((unsigned char)text[i]);
}
}
This parameter is char * rather than const char * because the function intentionally changes the buffer.
Using a const pointer locally
void replace_spaces(char *text) {
if (text == NULL) {
return;
}
char * const start = text;
for (; *text != '\0'; text++) {
if (*text == ' ') {
*text = '_';
}
}
/* start still holds the original buffer address. */
}
Here, start documents that the original address should not be reassigned. This can be useful locally, though it is less common than a pointer-to-const parameter.
Top-level const on a function parameter is usually not part of the function's external interface. For example, these declarations describe the same callable function type:
void process(char *text);
void process(char * const text);
The second form only restricts how text may be used inside the function implementation.
Common Mistakes
Confusing a constant pointer with a pointer to constant data
This declaration does not make the characters constant:
char * const pointer = buffer;
It only prevents pointer from being assigned a new address.
Attempting to write through const char *
const char *text = "hello";
// text[0] = 'H'; // Invalid
Use a writable array if you need to edit text:
char text[] = "hello";
text[0] = 'H';
Treating string literals as writable
This is unsafe in C and invalid in C++:
char *text = "hello";
A string literal must not be modified. Prefer:
const char *text = "hello";
Forgetting initialization for a const pointer
A const pointer must receive its address when declared:
char buffer[10];
char * const pointer = buffer;
This is invalid because there is no later opportunity to assign the pointer:
// char * const pointer;
Assuming const always makes an object completely immutable
const char *pointer prevents modification through that pointer. The underlying data may still be writable through another non-const pointer.
char buffer[] = "cat";
const char *reader = buffer;
char *writer = buffer;
writer[0] = 'C'; // Valid
/* reader now observes "Cat". */
Do not use this fact to bypass an object's intended read-only contract.
Comparisons
| Declaration | Can reassign the pointer? | Can modify characters through the pointer? | Meaning |
|---|---|---|---|
char *p | Yes | Yes | Pointer to mutable characters |
const char *p | Yes | No | Pointer to read-only characters |
char * const p | No | Yes | Fixed pointer to mutable characters |
const char * const p | No | No | Fixed pointer to read-only characters |
const char *p and char const *p are identical. Only the style differs.
Also distinguish a pointer from an array:
char text[] = "hi"; // Array storage; elements are writable
const char *text2 = "hi"; // Pointer to read-only characters
An array name cannot be reassigned, but that is an array rule, not the same as declaring a const pointer.
Cheat Sheet
char *p;
Pointer can move; characters can change.
const char *p;
char const *p;
Pointer can move; characters cannot change through p.
char * const p = buffer;
Pointer cannot move; characters can change.
const char * const p = "text";
Pointer cannot move; characters cannot change through p.
Rules:
constbefore the base type applies to pointed-to data:const char *.constafter*applies to the pointer:char * const.- A
constpointer needs an initializer. - Use
const char *for text that a function only reads. - Treat string literals as read-only; use
const char *for them. const char *does not guarantee that the underlying object can never change; it only prevents writes through that pointer.
FAQ
Is const char * the same as char const *?
Yes. Both declare a pointer to constant char data.
Can I change the pointer in const char *p?
Yes. p may point to a different character sequence. Only *p is read-only through p.
Can I change the pointer in char * const p?
No. The address stored in p is constant after initialization.
Can I modify a string literal through char * const?
No. char * const makes the pointer fixed; it does not make the pointed-to memory writable. Writing to a string literal has undefined behavior in C and is not allowed in C++.
Why does char * const need an initializer?
Because a const pointer cannot be assigned after it is declared. It must receive its one permitted address immediately.
Should a function parameter use char * const?
It can be useful inside an implementation, but callers generally do not see a difference. const char * is more important in an API because it tells callers their input will not be modified.
Does const char * make the original array constant?
No. It only prevents changes through that particular pointer. Other writable references to the same array can still modify it.
Mini Project
Description
Create a small C program that separates read-only labels from a writable text buffer. It demonstrates a common pattern: display text from a const char * and transform caller-provided text through a char * parameter.
Goal
Print a read-only label and convert a mutable message buffer to uppercase without changing the label.
Requirements
Create a function that accepts const char * and prints a label.
Create a function that accepts char * and converts its text to uppercase.
Store the label as a string literal through a const char *.
Store the message in a writable character array.
Print the message before and after converting it.
Keep learning
Related questions
2D Array Loop Order and Cache Performance in C
Learn why swapping nested loops changes 2D array performance in C, using row-major memory layout, cache locality, and practical benchmarks.
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.