365

What's the difference between:

char * const 

and

const char *
amiregelz
  • 1,833
  • 7
  • 25
  • 46
LB.
  • 13,730
  • 24
  • 67
  • 102
  • 4
    Possible duplicate of [What is the difference between const int\*, const int \* const, and int const \*?](http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const) – Emil Laine Feb 14 '16 at 13:07
  • 15
    The first thing to the left of the "const" is what's constant. If "const" is the thing the farthest to the left, then the first thing to the right of it is what's constant. – Cupcake Jul 31 '16 at 04:43
  • 9
    As a friendly tip, never forget that [cdecl](https://cdecl.org/) is a thing. – Braden Best Jun 16 '18 at 07:42
  • 1
    There is another char const* which is the return type of exception::what() – Zhang Jul 22 '19 at 03:14
  • 2
    ISO C++ FAQ: [What’s the difference between “const X* p”, “X* const p” and “const X* const p”?](https://isocpp.org/wiki/faq/const-correctness#const-ptr-vs-ptr-const) – legends2k Sep 21 '20 at 16:25

19 Answers19

456

The difference is that const char * is a pointer to a const char, while char * const is a constant pointer to a char.

The first, the value being pointed to can't be changed but the pointer can be. The second, the value being pointed at can change but the pointer can't (similar to a reference).

There is also a

const char * const

which is a constant pointer to a constant char (so nothing about it can be changed).

Note:

The following two forms are equivalent:

const char *

and

char const *

The exact reason for this is described in the C++ standard, but it's important to note and avoid the confusion. I know several coding standards that prefer:

char const

over

const char

(with or without pointer) so that the placement of the const element is the same as with a pointer const.

workmad3
  • 25,101
  • 4
  • 35
  • 56
  • 9
    Would it be worthwhile to note what happens if multiple variables are specified in the same declaration? I believe `const int *foo,*bar;` would declare both `foo` and `bar` to be `int const *`, but `int const *foo, *bar` would declare `foo` to be a `int const *` and `bar` to be `int *`. I think `typedef int * intptr; const intptr foo,bar;` would declare both variables to be `int * const`; I don't know any way to use a combined declaration to create two variables of that type without a typedef. – supercat Apr 12 '13 at 21:57
  • 2
    @supercat `I believe const int *foo,*bar; would declare both foo and bar to be int const *`: Yes. `but int const *foo, *bar would declare foo to be a int const * and bar to be int *`: _No!_ It would be exactly the same as the previous case. (See http://ideone.com/RsaB7n where you get the same error for both foo and bar). `I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const`: Yes. `I don't know any way to use a combined declaration to create two variables of that type without a typedef`: Well, `int *const foo, *const bar;`. C declarator syntax... – gx_ Aug 28 '13 at 18:35
  • @gx_: So I was wrong--my uncertainty was why I suggested that it might be helpful to say what the rules are. What would `int const *foo, *volatile bar` do to `bar`? Make it both `const` and `volatile`? I miss Pascal's clean separation of declared-variable names and their types (a pointer to an array of pointers to integers would be `var foo: ^Array[3..4] of ^Integer`;`. That'd be some funny nested parenthesized thing in C, I think. – supercat Aug 28 '13 at 18:54
  • 4
    @supercat (oh, C-only, sorry for the C++ code link, I got here from a C++ question) It's all about the _C declaration syntax_, with a ("pure") _type_ part followed by a _declarator_. In "`int const *foo, *volatile bar`" the type part is `int const` (stops before the `*`) and the declarators are `*foo` (the expression `*foo` will denote an `int const`) and `*volatile bar`; reading _right-to-left_ (good rule for _cv-qualifiers_), `foo` is a pointer to a _const_ int, and `bar` is a _volatile_ pointer to a _const_ int (the pointer itself is volatile, the pointed int is [accessed as] const). – gx_ Aug 28 '13 at 21:23
  • 1
    @supercat And as for "a pointer to an array of pointers to integers" (I don't know Pascal, not sure about the `[3..4]` syntax, so let's take an array of 10 elements): `int *(*foo)[10];`. It mirrors its (future) use as an expression: `*(*foo)[i]` (with `i` an integer in the range `[0, 10)` i.e. `[0, 9]`) will first dereference `foo` to get at the array, then access the element at index `i` (because postfix `[]` binds tighter than prefix `*`), then dereference this element, finally yielding an `int` (see http://ideone.com/jgjIjR ). But `typedef` makes it easier (see http://ideone.com/O3wb7d ). – gx_ Aug 28 '13 at 21:25
  • I've always completely avoided using multiple decls except in the simple case "int a,b,c;". I only recently discovered that "int const *p1, *p2" doesn't actually mean what I thought it probably did (as discussed above). Will continue to never use that form, since it's just a needless way to cause confusion. I think the only good reason to use these forms is if you are making a compiler compliance test suite :-) . – greggo Feb 11 '14 at 16:14
  • If you use const char* const ptr to the template void f(T param),f(ptr) in MSVC,the compiler will tell you the T is char const * and parameter is const char* – Tu Xiaomi Jan 15 '16 at 09:55
  • is "the value pointed **to**" the same as "the value pointed **at**"? – M.Ionut Jun 10 '20 at 12:01
  • It's to avoid a long discussion like the above that most coding standards (MISRA for example) explicitly disallow defining multiple variables on the same line. – Anonymouse Jul 01 '21 at 14:55
  • And what about: `const char* const*` ? – mohammadsdtmnd Dec 04 '22 at 17:47
139

To avoid confusion, always append the const qualifier.

int       *      mutable_pointer_to_mutable_int;
int const *      mutable_pointer_to_constant_int;
int       *const constant_pointer_to_mutable_int;
int const *const constant_pointer_to_constant_int;
diapir
  • 2,872
  • 1
  • 19
  • 26
  • 12
    Why? "To avoid confusion" doesn't explain what the confusion is to me. – Andrew Weir Nov 20 '13 at 11:48
  • 24
    @Andrew: I was hinting at consistency and thus readability. Writing all type qualifiers so they modify what's on their left, _always_, is what I use. – diapir Nov 20 '13 at 14:31
  • 3
    Actually it's the best answer on the subject I've found in SO – Trap Apr 22 '14 at 15:51
  • 8
    As a code standard, I have rarely encountered this style and so am not likely to adopt it. However as a learning tool, this answer was very helpful! (So I guess too bad this isn't more common style.) – natevw Sep 29 '14 at 21:33
  • 1
    Disagree, it would be more consistent to apply `const` to the thing that follows it. `const int * const p;` In the case of first `const`, it's int data that is constant. In the case of second `const`, it's `p` - the actual pointer variable that's constant. It doesn't make sense to apply const to `*`, but rather to `p`, so we should really prepend `const` to avoid confusion. – Alla Mar 20 '15 at 12:24
  • 11
    @Alla: `p` doesn't relate to the type : `(const int *const)`. For better or worse (worse if you ask me) the const qualifier, both in C and C++, is meant to be postfix : cf const member function `void foo(int a) const;`. The possibility to declare `const int` is the exception rather than the rule. – diapir Apr 09 '15 at 07:17
  • 1
    @diapir: I'm not sure that `const` type qualifier is "meant" to be postfix. Afterall, you wouldn't apply other type qualifiers, like `volatile` and `restrict` postfix, so why `const`? As for const member functions, it does not apply to C and in C++ member functions do have specifiers and modifiers incl. `const`, `override`, `final`, etc. applied postfix. But these are not type qualifiers (though for const the keyword used is indeed the same), so the rules for these need not necessarily apply to type declarations. – Alla Apr 10 '15 at 18:14
  • 1
    @Alla: Actually, `const` on member functions does qualify a type : the type of the implicit `this` pointer and thus the type of the function. `restrict` only qualifies pointers so it ends up to the right of the `*` anyway and I prefer `volatile` postfix myself. – diapir Apr 10 '15 at 23:53
  • 1
    "Writing all type qualifiers so they modify what's on their left" - That doesn't always work, though. I'm 99% sure something like `int unsigned typedef foo;` is not vali--what? That actually *works?* `echo "int unsigned typedef foo_t;" | gcc -c -xc - -o /dev/null` generates no compiler errors. Damn, C's type system is remarkably consistent. – Braden Best Jun 16 '18 at 07:30
  • 1
    I must have been thinking of `static`, which is a *storage specifier*, rather than a type qualifier.. – Braden Best Jun 16 '18 at 07:45
  • The other advantage of writing your declarations as @diapr has suggested is that for every instance of the word `const` the type of what is const qualified is everything to the left of the word, and the object that is const qualified is everything to the right. – dgnuff Jul 03 '18 at 01:19
  • A missing piece: this entire comment discussion suggests that we are totally free to decide what ordering to adopt, as if it's not defined in the std, and compilers haven't written yet! :) So: what _exactly_ gives us this freedom of placing `const` apparently wherever we wish, depending solely on our stylistic preferences? (Which is obviously not quite true, but "mostly" is, which then should not be quite obvious... E.g. [this answer](https://stackoverflow.com/a/5503442/1479945) tries to explain it, but still not 100% satisfactorily.) – Sz. Jul 14 '19 at 09:42
62

const always modifies the thing that comes before it (to the left of it), EXCEPT when it's the first thing in a type declaration, where it modifies the thing that comes after it (to the right of it).

So these two are the same:

int const *i1;
const int *i2;

they define pointers to a const int. You can change where i1 and i2 points, but you can't change the value they point at.

This:

int *const i3 = (int*) 0x12345678;

defines a const pointer to an integer and initializes it to point at memory location 12345678. You can change the int value at address 12345678, but you can't change the address that i3 points to.

Don McCaughey
  • 9,532
  • 3
  • 30
  • 36
27

const char* is a pointer to a constant character
char* const is a constant pointer to a character
const char* const is a constant pointer to a constant character

Andrew Coleson
  • 10,100
  • 8
  • 32
  • 30
25

Rule of thumb: read the definition from right to left!


const int *foo;

Means "foo points (*) to an int that cannot change (const)".
To the programmer this means "I will not change the value of what foo points to".

  • *foo = 123; or foo[0] = 123; would be invalid.
  • foo = &bar; is allowed.

int *const foo;

Means "foo cannot change (const) and points (*) to an int".
To the programmer this means "I will not change the memory address that foo refers to".

  • *foo = 123; or foo[0] = 123; is allowed.
  • foo = &bar; would be invalid.

const int *const foo;

Means "foo cannot change (const) and points (*) to an int that cannot change (const)".
To the programmer this means "I will not change the value of what foo points to, nor will I change the address that foo refers to".

  • *foo = 123; or foo[0] = 123; would be invalid.
  • foo = &bar; would be invalid.
Mr. Llama
  • 20,202
  • 2
  • 62
  • 115
23

const * char is invalid C code and is meaningless. Perhaps you meant to ask the difference between a const char * and a char const *, or possibly the difference between a const char * and a char * const?

See also:

Community
  • 1
  • 1
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
12
  1. const char* x Here X is basically a character pointer which is pointing to a constant value

  2. char* const x is refer to character pointer which is constant, but the location it is pointing can be change.

  3. const char* const x is combination to 1 and 2, means it is a constant character pointer which is pointing to constant value.

  4. const *char x will cause a compiler error. it can not be declared.

  5. char const * x is equal to point 1.

the rule of thumb is if const is with var name then the pointer will be constant but the pointing location can be changed , else pointer will point to a constant location and pointer can point to another location but the pointing location content can not be change.

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
AAnkit
  • 27,299
  • 12
  • 60
  • 71
  • 2
    "char* const x is refer to character pointer which is constant, but the location it is pointing can be change." Wrong. The value at the location can be changed not the location itself. – PleaseHelp Mar 12 '15 at 13:44
6

Another thumb rule is to check where const is:

  1. before * => value stored is constant
  2. after * => pointer itself is constant
Aadishri
  • 1,341
  • 2
  • 18
  • 26
4

Lots of answer provide specific techniques, rule of thumbs etc to understand this particular instance of variable declaration. But there is a generic technique of understand any declaration:

Clockwise/Spiral Rule

A)

const char *a;

As per the clockwise/spiral rule a is pointer to character that is constant. Which means character is constant but the pointer can change. i.e. a = "other string"; is fine but a[2] = 'c'; will fail to compile

B)

char * const a;

As per the rule, a is const pointer to a character. i.e. You can do a[2] = 'c'; but you cannot do a = "other string";

JamesWebbTelescopeAlien
  • 3,547
  • 2
  • 30
  • 51
  • 2
    Also known as right-left rule (at least that's how I learnt it): http://jdurrett.ba.ttu.edu/3345/handouts/RL-rule.html – Tomas Pruzina May 09 '18 at 12:05
  • 1
    (Would be much better if the essence of the answer would not be hidden behind a link, with the text here not even citing, or at least referring, to any of its specifics, beyond a generic "as per the rule".) – Sz. Jul 14 '19 at 09:58
  • @Sz. Do you have any specific confusion here that I can clear? There is really not much to it after knowing the rule. – JamesWebbTelescopeAlien Jul 15 '19 at 01:53
4

First one is a syntax error. Maybe you meant the difference between

const char * mychar

and

char * const mychar

In that case, the first one is a pointer to data that can't change, and the second one is a pointer that will always point to the same address.

Javier
  • 4,552
  • 7
  • 36
  • 46
2

Here is a detailed explanation with code

/*const char * p;
char * const p; 
const char * const p;*/ // these are the three conditions,

// const char *p;const char * const p; pointer value cannot be changed

// char * const p; pointer address cannot be changed

// const char * const p; both cannot be changed.

#include<stdio.h>

/*int main()
{
    const char * p; // value cannot be changed
    char z;
    //*p = 'c'; // this will not work
    p = &z;
    printf(" %c\n",*p);
    return 0;
}*/

/*int main()
{
    char * const p; // address cannot be changed
    char z;
    *p = 'c'; 
    //p = &z;   // this will not work
    printf(" %c\n",*p);
    return 0;
}*/



/*int main()
{
    const char * const p; // both address and value cannot be changed
    char z;
    *p = 'c'; // this will not work
    p = &z; // this will not work
    printf(" %c\n",*p);
    return 0;
}*/
Reese Moore
  • 11,524
  • 3
  • 24
  • 32
Megharaj
  • 1,589
  • 2
  • 20
  • 32
2

char * const and const char *?

  1. Pointing to a constant value

const char * p; // value cannot be changed

  1. Constant pointer to a value

char * const p; // address cannot be changed

  1. Constant pointer to a constant value

const char * const p; // both cannot be changed.

Yogeesh H T
  • 2,777
  • 21
  • 18
1
// Some more complex constant variable/pointer declaration.
// Observing cases when we get error and warning would help
// understanding it better.

int main(void)
{
  char ca1[10]= "aaaa"; // char array 1
  char ca2[10]= "bbbb"; // char array 2

  char *pca1= ca1;
  char *pca2= ca2;

  char const *ccs= pca1;
  char * const csc= pca2;
  ccs[1]='m';  // Bad - error: assignment of read-only location ‘*(ccs + 1u)’
  ccs= csc;    // Good

  csc[1]='n';  // Good
  csc= ccs;    // Bad - error: assignment of read-only variable ‘csc’

  char const **ccss= &ccs;     // Good
  char const **ccss1= &csc;    // Bad - warning: initialization from incompatible pointer type

  char * const *cscs= &csc;    // Good
  char * const *cscs1= &ccs;   // Bad - warning: initialization from incompatible pointer type

  char ** const cssc=   &pca1; // Good
  char ** const cssc1=  &ccs;  // Bad - warning: initialization from incompatible pointer type
  char ** const cssc2=  &csc;  // Bad - warning: initialization discards ‘const’
                               //                qualifier from pointer target type

  *ccss[1]= 'x'; // Bad - error: assignment of read-only location ‘**(ccss + 8u)’
  *ccss= ccs;    // Good
  *ccss= csc;    // Good
  ccss= ccss1;   // Good
  ccss= cscs;    // Bad - warning: assignment from incompatible pointer type

  *cscs[1]= 'y'; // Good
  *cscs= ccs;    // Bad - error: assignment of read-only location ‘*cscs’
  *cscs= csc;    // Bad - error: assignment of read-only location ‘*cscs’
  cscs= cscs1;   // Good
  cscs= cssc;    // Good

  *cssc[1]= 'z'; // Good
  *cssc= ccs;    // Bad - warning: assignment discards ‘const’
                 //                qualifier from pointer target type
  *cssc= csc;    // Good
  *cssc= pca2;   // Good
  cssc= ccss;    // Bad - error: assignment of read-only variable ‘cssc’
  cssc= cscs;    // Bad - error: assignment of read-only variable ‘cssc’
  cssc= cssc1;   // Bad - error: assignment of read-only variable ‘cssc’
}
1
  1. Constant pointer: A constant pointer can point only to a single variable of the respective data type during the entire program.we can change the value of the variable pointed by the pointer. Initialization should be done during the time of declaration itself.

Syntax:

datatype *const var;

char *const comes under this case.

/*program to illustrate the behaviour of constant pointer */

#include<stdio.h>
int main(){
  int a=10;
  int *const ptr=&a;
  *ptr=100;/* we can change the value of object but we cannot point it to another variable.suppose another variable int b=20; and ptr=&b; gives you error*/
  printf("%d",*ptr);
  return 0;
}
  1. Pointer to a const value: In this a pointer can point any number of variables of the respective type but we cannot change the value of the object pointed by the pointer at that specific time.

Syntax:

const datatype *varor datatype const *var

const char* comes under this case.

/* program to illustrate the behavior of pointer to a constant*/

   #include<stdio.h>
   int main(){
       int a=10,b=20;
       int const *ptr=&a;
       printf("%d\n",*ptr);
       /*  *ptr=100 is not possible i.e we cannot change the value of the object pointed by the pointer*/
       ptr=&b;
       printf("%d",*ptr);
       /*we can point it to another object*/
       return 0;
    }
Ram
  • 3,092
  • 10
  • 40
  • 56
1

The const modifier is applied to the term immediately to its left. The only exception to this is when there is nothing to its left, then it applies to what is immediately on its right.

These are all equivalent ways of saying "constant pointer to a constant char":

  • const char * const
  • const char const *
  • char const * const
  • char const const *
galois
  • 825
  • 2
  • 11
  • 31
  • Is it compiler dependent? gcc produce for "const char const *" and "const const char *" and "char const const *" the same result -> pointer could pointing to other location. – cosinus0 Aug 04 '17 at 08:57
1

Two rules

  1. If const is between char and *, it will affect the left one.
  2. If const is not between char and *, it will affect the nearest one.

e.g.

  1. char const *. This is a pointer points to a constant char.
  2. char * const. This is a constant pointer points to a char.
Jishnu V S
  • 8,164
  • 7
  • 27
  • 57
1

I would like to point out that using int const * (or const int *) isn't about a pointer pointing to a const int variable, but that this variable is const for this specific pointer.

For example:

int var = 10;
int const * _p = &var;

The code above compiles perfectly fine. _p points to a const variable, although var itself isn't constant.

SteliosKts
  • 65
  • 1
  • 9
1

I remember from Czech book about C: read the declaration that you start with the variable and go left. So for

char * const a;

you can read as: "a is variable of type constant pointer to char",

char const * a;

you can read as: "a is a pointer to constant variable of type char. I hope this helps.

Bonus:

const char * const a;

You will read as a is constant pointer to constant variable of type char.

Sany
  • 103
  • 2
  • 8
1

I presume you mean const char * and char * const .

The first, const char *, is a pointer to a constant character. The pointer itself is mutable.

The second, char * const is a constant pointer to a character. The pointer cannot change, the character it points to can.

And then there is const char * const where the pointer and character cannot change.

Michael
  • 54,279
  • 5
  • 125
  • 144