Constant pointers: In constant pointers, the pointer points to a fixed memory location, and the value at that location can be changed because it is a variable, but the pointer will always point to the same location because it is made constant here.
A constant pointer is a pointer that cannot change the address its holding. In other words, we can say that once a constant pointer points to a variable then it cannot point to any other variable. In the above example : We declared two variables var1 and var2.
A constant pointer is a pointer that holds the address of only one location during it's entire lifetime whereas a pointer pointing to the location of a constant variable is a pointer to constant.
What is the benefit of const keyword in programming? Specifying a variable as const states that the variable's value should never change after the initial assignment. This allows the compiler to perform additional tests at compilation (validating your code).
const
is a tool which you should use in pursuit of a very important C++ concept:
Find bugs at compile-time, rather than run-time, by getting the compiler to enforce what you mean.
Even though it doesn't change the functionality, adding const
generates a compiler error when you're doing things you didn't mean to do. Imagine the following typo:
void foo(int* ptr)
{
ptr = 0;// oops, I meant *ptr = 0
}
If you use int* const
, this would generate a compiler error because you're changing the value to ptr
. Adding restrictions via syntax is a good thing in general. Just don't take it too far -- the example you gave is a case where most people don't bother using const
.
I make a point of using only const
arguments because this enables more compiler checks: if I accidentally re-assign an argument value inside the function, the compiler bites me.
I rarely reuse variables, it’s cleaner to create new variables to hold new values, so essentially all my variable declarations are const
(except for some cases such as loop variables where const
would prevent the code from working).
Note that this makes only sense in the definition of a function. It doesn’t belong in the declaration, which is what the user sees. And the user doesn’t care whether I use const
for parameters inside the function.
Example:
// foo.h
int frob(int x);
// foo.cpp
int frob(int const x) {
MyConfigType const config = get_the_config();
return x * config.scaling;
}
Notice how both the argument and the local variable are const
. Neither is necessary but with functions that are even slightly larger, this has repeatedly saved me from making mistakes.
Your question touches on something more general: Should function arguments be const?
The constness of value arguments (like your pointer) is an implementation detail, and it does not form part of the function declaration. This means that your function is always this:
void foo(T);
It is entirely up to the implementer of the function whether she wants to use the functions-scope argument variable in a mutable or in a constant way:
// implementation 1
void foo(T const x)
{
// I won't touch x
T y = x;
// ...
}
// implementation 2
void foo(T x)
{
// l33t coding skillz
while (*x-- = zap()) { /* ... */ }
}
So, follow the simple rule to never put const
in the declaration (header), and put it in the definition (implementation) if you don't want or need to modify the variable.
The top level const qualifier is discarded in declarations, so the declarations in the question declare exactly the same function. On the other hand, in the definition (implementation) the compiler will verify that if you mark the pointer as const, it is not modified inside the body of the function.
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;
You're right, for the caller it makes absolutely no difference. But for the writer of the function it can be a safety net "okay, I need to make sure I don't make this point to the wrong thing". Not very useful but not useless either.
It's basically the same as having an int const the_answer = 42
in your program.
...today I realized that pointers are passed by value to functions, which makes sense.
(imo) it really doesn't make sense as the default. the more sensible default is to pass as non-reassignable pointer (int* const arg
). that is, i would have preferred that pointers passed as arguments were implicitly declared const.
So what's the advantage of const?
the advantage is that it's easy enough and sometimes unclear when you do modify the address the argument points to, such that you can introduce a bug when it is not const rather easily. altering the address is atypical. it's clearer to create a local variable if your intent is to modify the address. as well, raw pointer manipulation is an easy way to introduce bugs.
so it's clearer to pass by immutable address and create a copy (in those atypical cases) when you want to alter the address the argument points to:
void func(int* const arg) {
int* a(arg);
...
*a++ = value;
}
adding that local is virtually free, and it reduces the chance for errors, while improving readability.
at a higher level: if you are manipulating the argument as an array, it's typically clearer and less error prone to the client to declare the argument as a container/collection.
in general, adding const to values, arguments, and addresses is a good idea because you don't always realize the side effects, which the compiler happily enforces. therefore, it's as useful as const as used in other several other cases (e.g. the question is similar to 'Why should I declare values const?'). fortunately, we also have references, which cannot be reassigned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With