Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `const` work on the thing immediately preceding it?

I am learning C++. In my course, it is explained that it is best to place const immediately after the thing you want to make unchangeable, because this is how const works.

Many people, including for instance Bjarne Stroustrup himself, like to write const in front. But this sometimes leads to problems:

const int *foo; //modifiable pointer to a constant int. 
int const *bar; //constant pointer to a modifiable int? No! It's a modifiable pointer to a constant int. (So the same type as foo)

An example that shows this in action:

int fun(int const *mypointer)
{
    *mypointer = 5; //Won't compile, because constant int.
    mypointer = 0; // Is okay, because modifiable pointer.
}

What makes this even more confusing, is that compilers such as g++ like to rewrite int const bar to const int bar in their error messages.

Now, this behaviour is confusing me greatly. Why does const work in this way? It would seem a lot easier to understand if it would 'just' work on the thing put after it.

like image 988
Qqwy Avatar asked Oct 07 '16 08:10

Qqwy


2 Answers

C++ follows syntax of C.

It looks weird, but in C you specify not a type of variable, but a type of expression with it:

  • int v means that v is int;
  • int *v means that *v is int, so v is pointer to int;
  • int v[] means that v[…] is int, so v is array of int;
  • int v() means that v() is int, so v is function returning int;
  • etc (you always need to read such declaration from inner).

More closely to your question, in C type specification can consist of several words: unsigned char, long int, const double (even more than two — const unsigned long long int). Number of repeated words matters (long long int in general case is different from long int), but order of words doesn't (long int is the same as int long). That's why const int *p is the same as int const *p (as well as const int i is the same as int const i).

As for int * const p, it probably doesn't obey common scheme. As there is no such expression as * const p (where p is a variable) in C, so we can't explain it with something like "expression * const p will have type int". However, think, where else can we put const keyword to specify that pointer itself is constant, not its dereferenced value? (Assuming that both const int *p and int const *p mean that a dereferenced value is constant, and we don't want to introduce additional keywords into language.) Nowhere except after *; so here it goes.

like image 137
Sasha Avatar answered Sep 18 '22 09:09

Sasha


To understand a C declaration there is a Right-Left rule that is very helpful: For example

int *

is a pointer to an integer (note that you have to read that right to left). Same thing for reference to int:

int &

Now read the type of p8 from right to left:

char * const * const p8; //  const pointer to const pointer to char

I suspect that const modifies the preceding type, just to be consistent with that rule. The fact that you can put const in the very beginning of the declaration is an exception.

Note: the example comes from this article (but I changed it slightly).

like image 38
esam Avatar answered Sep 20 '22 09:09

esam