Sign in to follow this  

[C++] Pointer arithmetics and const correctness

This topic is 3114 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

It's so easy to break the const correctness using pointer arithmetics!
#include <iostream>

int* ConstCast(const int* p)
{
  int* a = 0;
  return p - a + a;
}

int* ConstCast2(const int* p)
{
  int* a = 0;
  while (a < p) a++; // actually equivalent to "a += p-a"
  return a;
}

int main()
{
  int i = 5;
  const int* p = &i;
  int* r = ConstCast(p);
  *r = 666;
  std::cout << i; // output 666 if "i" is declared non-const
}

To prevent the compilation of ConstCast we need that pointer subtractions which involve a const-pointer return a type that can not be added to a non-const pointer. To prevent the compilation of ConstCast2 we must forbid the comparison between const and non-const pointers; but we can always convert a non-const pointer to a const one before the comparison. So it is impossible to design pointer arithmetics without allowing trivial ways to break const correctness? PS1: This just mind training, I can not change the C++ specifications! PS2: I am sorry if this has been already discussed, but "pointer arithmetics" and "const correctness" are two topics so much discussed that I could not find anything on them together.

Share this post


Link to post
Share on other sites
Yes, you can break const correctness like this. In fact, you can break const correctness even easier by using const_cast which is built into the language.

You can also break C++ in dozens of other ways, if you really want to.

The point is that the language expects you to at least try to do the right thing. You can do the wrong thing if you really want, but don't be surprised when it bites you.

Share this post


Link to post
Share on other sites
Pointer arithmetic is only valid under certain conditions. You can point to an object (or an array of objects), and you can point one past the end. All other pointer arithmetic is undefined.

Lets assume it is allowed. Even then, you are not technically breaking the rules. Const means "read only through this reference". So in both your ConstCasts, you are never writing through the const reference you are given.

Finally, nearly all C++'s compile time protections (const, private) can be subverted by a sufficiently determined programmer.

Share this post


Link to post
Share on other sites
Actually, according to the rules of pointer arithmetic, both of your examples are undefined behavior. In particular, if you pass an unaligned pointer you're probably not going to get the same value back. Ex:

int * orig = (int *)0x0FF3;

int * r1 = ConstCast(orig);
std::cout << (void *)r1 << std::endl;

int * r2 = ConstCast2(orig);
std::cout << (void *)r2 << std::endl;

On MSVC 2008 you get back 0FF0 and 0FF4 rather than 0FF3.

Share this post


Link to post
Share on other sites
Static code analyzers will warn of such situations. While not standard practice, I did use PCLint (or some similar tool) on a project some time ago, and it properly reported indirect modification of const value, even in some incredibly obscure call chains (5-6 functions deep, caused by temporaries).

While it made sense at some point, I don't know why C++ compilers don't include full analysis during compilation. In my experience, compilation is the fast part these days, it's linking that takes forever.

Also, this is a good example why it makes sense to use one of array wrappers, even a self-written one. C doesn't have const-guarantee to the degree C++ does, and pointer arithmetic is a C concept, C++ has iterators.

Share this post


Link to post
Share on other sites

This topic is 3114 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this