Consider this union:
union A{
int a;
struct{
int b;
} c;
};
c
and a
are not layout-compatibles types so it is not possible to read the value of b
through a
:
A x;
x.c.b=10;
x.a+x.a; //undefined behaviour (UB)
Trial 1
For the case below I think that since C++17, I also get an undefined behavior:
A x;
x.a=10;
auto p = &x.a; //(1)
x.c.b=12; //(2)
*p+*p; //(3) UB
Let's consider [basic.type]/3:
Every value of pointer type is one of the following:
- a pointer to an object or function (the pointer is said to point to the object or function), or
- a pointer past the end of an object ([expr.add]), or
- the null pointer value ([conv.ptr]) for that type, or
- an invalid pointer value.
Let's call this 4 pointer values categories as pointer value genre.
The value of a pointer may transition from of the above mentioned genre to an other, but the standard is not really explicit about that. Fill free to correct me if I am wrong. So I suppose that at (1) the value of p
is a pointer to value. Then in (2) a
life ends and the value of p
becomes an invalid pointer value. So in (3) I get UB because I try to access the value of an object (a
) out of its lifetime.
Trial 2
Now consider this weird code:
A x;
x.a=10;
auto p = &x.a; //(1)
x.c.b=12; //(2)
p = reinterpret_cast<int*>(p); //(2')
*p+*p; //(3) UB?
Could the reinterpret_cast<int*>(p)
change the pointer value genre from invalid pointer value
to a pointer to
value.
reinterpret_cast<int*>(p)
is defined to be equivalent to static_cast<int*>(static_cast<void*>(p))
, so let's consider how is defined the static_cast
from void*
to int*
, [expr.static.cast]/13:
A prvalue of type “pointer to
cv1 void
” can be converted to a prvalue of type “pointer tocv2 T
”, whereT
is an object type andcv2
is the same cv-qualification as, or greater cv-qualification than,cv1
. If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement ofT
, then the resulting pointer value is unspecified. Otherwise, if the original pointer value points to an object a, and there is an object b of typeT
(ignoring cv-qualification) that is pointer-interconvertible with a, the result is a pointer to b. Otherwise, the pointer value is unchanged by the conversion.
So in our case the original pointer pointed to the object a
. So I suppose the reinterpret_cast
will not help because a
is not within its lifetime. Is my reading to strict? Could this code be well defined?