Tuff Contender
Tuff Contender

Reputation: 269

Is casting a pointer to const pointer and cast back to the original type undefined?

I know casting a const pointer to non-const type might be undefined behavior, but what if the pointer is originally not const?

int i = 0;
int * pi = &i;
const int * const_pi = const_cast<const int*>(pi);
int * non_const_pi = const_cast<int*>(const_pi);
*non_const_pi = 0;
*non_const_pi = 1;
int j = *non_const_pi;

Is there's any undefined behavior? If any, where do they happen? May the compiler assume that non_const_pi is casted from a const pointer and perform no modification?

Upvotes: 1

Views: 11079

Answers (2)

R Sahu
R Sahu

Reputation: 206737

I know casting a const pointer to non-const type might be undefined behavior.

That is a misunderstanding.

Const-casting pointers is never cause for undefined behavior. Dereferencing a non-const pointer obtained by way of const_cast-ing a const pointer to a const object is not undefined behavior either if the original object is used in read-only mode. It is undefined behavior if you try to write to the object.

int const i = 10;
int const* p1 = &i;
int* p2 = const_cast<int*>(p1);  // OK.
std::cout << *p2;                // Still OK.
*p2 = 20;                        // Not OK.

Given that, your second block of code is perfectly OK. There is no undefined behavior since the original object is a non-const object.

From The Standard, Section 5.2.11, Expressions/Const cast :

The result of a pointer const_cast refers to the original object.

Upvotes: 6

songyuanyao
songyuanyao

Reputation: 173044

No, this is not UB. Only when trying to modify a const object through a non-const access path results in UB. For this case, non_const_pi is pointing to a non-const object i in fact, then modifying through it is fine.

There's an exact example in the standard, [dcl.type.cv]/4:

... any attempt to modify ([expr.ass], [expr.post.incr], [expr.pre.incr]) a const object ([basic.type.qualifier]) during its lifetime ([basic.life]) results in undefined behavior. [ Example:

...

int i = 2;                              // not cv-qualified
const int* cip;                         // pointer to const int
cip = &i;                               // OK: cv-qualified access path to unqualified
*cip = 4;                               // ill-formed: attempt to modify through ptr to const

int* ip;
ip = const_cast<int*>(cip);             // cast needed to convert const int* to int*
*ip = 4;                                // defined: *ip points to i, a non-const object

Upvotes: 5

Related Questions