I\'m not talking about pointers to const values, but const pointers themselves.
I\'m learning C and C++ beyond the very basic stuff and just until today I realized t
There is a lot to the const keyword, it is a rather complex one. Generally, adding a lot of const to your program is considered good programming practice, search the web for "const correctness" and you'll find plenty of info about that.
The const keyword is a so-called "type qualifier", others are volatile and restrict. At least volatile follows the same (confusing) rules as const.
First of all, the const keyword serves two purposes. The most obvious one is to protect data (and pointers) from intentional or accidental misuse by making them read-only. Any attempt to modify a const variable will be spotted by the compiler at compile-time.
But there is also another purpose in any system with read-only memory, namely to ensure that a certain variable is allocated inside such memory - it could be EEPROM or flash for example. These are known as non-volatile memories, NVM. A variable allocated in NVM will still of course follow all the rules of a const variable.
There are several different ways to use the const keyword:
Declare a constant variable.
This can be done either as
const int X=1; or
int const X=1;
These two forms are completely equivalent. The latter style is considered bad style and should not be used.
The reason why the second row is considered bad style, is probably because "storage-class specifiers" such as static and extern also can be declared after the actual type, int static etc. But doing so for storage-class specifiers is labelled as an obsolete feature by the C committee (ISO 9899 N1539 draft, 6.11.5). Therefore, for the sake of consistency one should not write type qualifiers in that manner either. It serves no other purpose but to confuse the reader anyhow.
Declare a pointer to a constant variable.
const int* ptr = &X;
This means that the contents of 'X' cannot be modified. This is the normal way you declare pointers like this, mainly as part of function parameters for "const correctness". Because 'X' doesn't actually have to be declared as const, it could be any variable. In other words you can always "upgrade" a variable to const. Technically, C also allows downgrading from const to a plain variable by explicit typecasts, but doing so is considered bad programming and compilers usually give warnings against it.
Declare a constant pointer
int* const ptr = &X;
This means that the pointer itself is constant. You can modify what it points at, but you cannot modify the pointer itself. This doesn't have many uses, there are a few, like ensuring that a pointer-pointed-at (pointer-to-pointer) doesn't have it's address changed while passed as parameter to a function. You'll have to write something not-too-readable like this:
void func (int*const* ptrptr)
I doubt many C programmers can get the const and * right in there. I know I can't - I had to check with GCC. I think that's why you rarely ever see that syntax for pointer-to-pointer, even though it is considered good programming practice.
Constant pointers can also be used to ensure that the pointer variable itself is declared in read-only memory, for example you could want to declare some sort of pointer-based lookup table and allocate it in NVM.
And of course, as indicated by other answers, constant pointers can also be used to enforce "const correctness".
Declare a constant pointer to constant data
const int* const ptr=&X;
This is the two pointer types described above combined, with all attributes of them both.
Declare a read-only member function (C++)
Since this is tagged C++, I should also mention that you can declare member functions of a class as const. This means that the function isn't allowed to modify any other member of the class when it is called, which both prevents the programmer of the class from accidental errors but also informs the caller of the member function that they won't be messing anything up by calling it. The syntax is:
void MyClass::func (void) const;