Const char * const versus const char *?

I run some sample programs to re-evaluate myself using C ++, and I came across the following question. Firstly, here is a sample code:

void print_string(const char * the_string) { cout << the_string << endl; } int main () { print_string("What up?"); } 

In the above code, the print_string parameter could be const char * const the_string . What would be more correct for this?

I understand that the difference is that it is a pointer to a constant character, and one is a constant pointer to a constant character. But why both of these work? When will this be relevant?

+85
c ++ c
09 Feb '11 at 19:02
source share
12 answers

The latter does not allow you to change the_string inside print_string . Actually, that would be appropriate, but perhaps verbosity delayed the developer.

char* the_string : I can change the char that the_string points the_string , and I can change the char that it points to.

const char* the_string : I can change the char that the_string points the_string , but I can't change the char that it points to.

char* const the_string : I cannot change the char that the_string points the_string , but I can change the char that it points to.

const char* const the_string : I cannot change the char that the_string points the_string , and I cannot change the char in which it points.

+196
Feb 09 '11 at 19:05
source share
  • Character pointer to mutable character

     char *p; 
  • Variable pointer to a constant character

     const char *p; 
  • Permanent pointer to mutable character

     char * const p; 
  • Permanent pointer to a constant character

     const char * const p; 
+102
Feb 09 2018-11-11T00:
source share

const char * const means a pointer, as well as the data the pointer points to, both const!

const char * means only the data pointed to by a pointer is a constant. however, the pointer itself is not const.

Example.

 const char *p = "Nawaz"; p[2] = 'S'; //error, changing the const data! p="Sarfaraz"; //okay, changing the non-const pointer. const char * const p = "Nawaz"; p[2] = 'S'; //error, changing the const data! p="Sarfaraz"; //error, changing the const pointer. 
+24
Feb 09 '11 at 19:07
source share

Many people suggest reading a type specifier from right to left.

 const char * // Pointer to a `char` that is constant, it can't be changed. const char * const // A const pointer to const data. 

In both forms, a pointer indicates persistent or read-only data.

In the second form, the pointer cannot be changed; the pointer always points to the same place.

+12
Feb 09 '11 at 19:07
source share

(I know this is old, but I still wanted to share).

I just wanted to clarify the answer of Thomas Matthews. The Right-Left Rule of type C declarations says pretty much: when reading a type C declaration, start with the identifier and go right when you can and leave when you cannot.

This is best explained with a few examples:

Example 1

  • Start with the id, we cannot go right, so we go left

     const char* const foo ^^^^^ 

    foo - constant ...

  • Continue left

     const char* const foo ^ 

    foo is a constant pointer to ...

  • Continue left

     const char* const foo ^^^^ 

    foo is a constant pointer to char ...

  • Continue left

     const char* const foo ^^^^^ 

    foo - constant pointer to char constant (full!)

Example 2

  • Start with the id, we cannot go right, so we go left

     char* const foo ^^^^^ 

    foo - constant ...

  • Continue left

     char* const foo ^ 

    foo is a constant pointer to ...

  • Continue left

     char* const foo ^^^^ 

    foo - constant pointer to char (full!)

Example 1337

  • Start with the id, but now we can go right!

     const char* const* (*foo[8])() ^^^ 

    foo - an array of 8 ...

  • Hit parentheses so that can no longer go, go left

     const char* const* (*foo[8])() ^ 

    foo - an array of 8 pointers to ...

  • Finished inside the brackets, now you can go right

     const char* const* (*foo[8])() ^^ 

    foo is an array of 8 pointers to a function that returns ...

  • Nothing more right, go left

     const char* const* (*foo[8])() ^ 

    foo is an array of 8 pointers to a function that returns a pointer to ...

  • Continue left

     const char* const* (*foo[8])() ^^^^^ 

    foo is an array of 8 function pointers that return a pointer to a constant ...

  • Continue left

     const char* const* (*foo[8])() ^ 

    foo is an array of 8 function pointers that return a pointer to a constant pointer to ...

  • Continue left

     const char* const* (*foo[8])() ^^^^ 

    foo is an array of 8 function pointers that return a pointer to a constant pointer to char ...

  • Continue left

     const char* const* (*foo[8])() ^^^^^ 

    foo is an array of 8 function pointers that return a pointer to a constant pointer to a constant char constant (Complete!)

Further explanation: http://www.unixwiz.net/techtips/reading-cdecl.html

+11
Mar 21 '16 at 3:27
source share

The difference is that without an additional const programmer can change inside the method pointed to by the pointer; eg:

  void print_string(const char * the_string) { cout << the_string << endl; //.... the_string = another_string(); //.... } 

This would be illegal if the signature were void print_string(const char * const the_string)

Many programmers consider the extra const keyword to be too verbose (in most scenarios) and omit it, even if it would be semantically correct.

+3
Feb 09 '11 at 19:09
source share

In the latter, you guarantee not to change both the pointer and the character in the first, you only guarantee that the contents will not change, but you can move the pointer around

+2
Feb 09 '11 at 19:04
source share

There is no reason why no one will work. All print_string() does this value. He is not trying to modify it.

A good idea is to make a function that does not change the arguments of the labels as const. The advantage is that variables that cannot be changed (or you do not want to change) can be passed to these functions without errors.

Regarding the exact syntax, you want to indicate which type of argument is "safe" for passing the function.

+2
Feb 09 2018-11-11T00:
source share

I think this is rarely relevant because your function is not called with arguments like & * the_string or ** the_string. The pointer itself is a value type argument, so even if you change it, you are not going to change the copy that was used to call your function. The displayed version ensures that the string does not change, and I think that in this case will be enough.

+2
Oct 23
source share

const char * means you cannot use a pointer to change what it points to. You can change the pointer to point to something else.

Consider:

 const char * promptTextWithDefault(const char * text) { if ((text == NULL) || (*text == '\0')) text = "C>"; return text; } 

The parameter is a non-constant pointer to const char, so it can be changed to another const char * value (for example, a constant string). If, however, we mistakenly wrote *text = '\0' , then we would get a compilation error.

Perhaps if you are not going to change what this parameter points to, you can make the const char * const text parameter, but it is not. Usually we allow functions to change the values โ€‹โ€‹passed to the parameters (since we pass parameters by value, any change does not affect the caller).

By the way: it is good practice to avoid char const * , because it is often read incorrectly - this means the same as const char * , but too many people read it as a char * const value.

+2
Dec 29 '15 at 11:28
source share

Almost all the other answers are correct, but they miss one aspect of this: when you use an extra const for a parameter in a function declaration, the compiler essentially ignores it. For a moment, let it ignore the complexity of your pointer example, and just use int .

 void foo(const int x); 

declares the same function as

 void foo(int x); 

Only in the function definition is there an additional const significant:

 void foo(const int x) { // do something with x here, but you cannot change it } 

This definition is compatible with any of the above ads. The caller does not care that x - const is an implementation detail that is not related to the call site.

If you have a const pointer to const data, the same rules apply:

 // these declarations are equivalent void print_string(const char * const the_string); void print_string(const char * the_string); // In this definition, you cannot change the value of the pointer within the // body of the function. It essentially a const local variable. void print_string(const char * const the_string) { cout << the_string << endl; the_string = nullptr; // COMPILER ERROR HERE } // In this definition, you can change the value of the pointer (but you // still can't change the data it pointed to). And even if you change // the_string, that has no effect outside this function. void print_string(const char * the_string) { cout << the_string << endl; the_string = nullptr; // OK, but not observable outside this func } 

Few C ++ programmers try to make const parameters, even if they can be, regardless of whether these parameters are pointers.

0
Mar 03 '16 at 0:41
source share

The difference between the two is that char * can point to any arbitrary pointer. Const char *, in contrast, points to the constants defined in the DATA section of the executable. And thus, you cannot change the character values โ€‹โ€‹of the string const char *.

-one
09 Feb '11 at 19:03
source share



All Articles