I am trying to determine if the following code causes undefined behavior:
I understand that reinterpret_cast to and from char* compatible, because the standard allows overlay using char and unsigned char pointers (my selection):
If the program tries to access the stored value of the object through an l value other than one of the following types, the behavior is undefined:
- dynamic type of object
- cv-qualified version of the dynamic type of an object,
- a type that is a signed or unsigned type corresponding to a dynamic type of an object,
- a type that is a signed or unsigned type corresponding to the receipt version of the dynamic type of an object,
- a collection or type of association that includes one of the above types among its members (including recursively, a member of a subgroup, or a union)
- a type that is (possibly cv-qualified) a base class type of a dynamic object type,
- a
char or unsigned char .
However, I'm not sure if f(*a) causes undefined behavior by creating an A& reference to an invalid pointer. The decisive factor, apparently, is that it "tries to gain access" to the word formation tools in the context of the C ++ standard.
My intuition is that this is not access, since access will require A to determine (it is declared, but not defined in this example). Unfortunately, I cannot find a specific definition of "access" in the C ++ standard:
Does f(*a) perform undefined behavior? What does βaccessβ mean in the C ++ standard?
I understand that, regardless of the answer, it is hardly worth relying on this behavior in production code. I ask this question primarily out of a desire to improve my understanding of the language.
[Edit] @SergeyA quoted this section of the standard. I have included it here for easy reference (emphasis mine):
5.3.1 / 1 [expr.unary.op]
The unary operator * performs an indirect call: the expression to which it is applied must be a pointer to the type of the object or a pointer to the type of the function, and the result is the value l related to the object or function, the point of expression. If the type of the expression is a "pointer to T ", then the result type is " T ". [Note: it is incorrect to indicate a pointer to an incomplete type (except for cv void). The lval thus obtained can be used in a limited way (for example, to initialize a link); this lvalue value should not be converted to prvalue, see 4.1. - end of note]
Tracking the link to 4.1, we find:
4.1 / 1 [conv.lval]
The value gl (3.10) of a non-function type without an array T can be converted to prvalue. If T is an incomplete type, a program that requires this conversion is poorly formed. If T is a non-class type, the prvalue type is a cv-unqualified version of T Otherwise, the prvalue type will be T
When the lvalue-rvalue transform is applied to the expression e and either:
e not evaluated potentially, or- evaluating
e leads to evaluating the term ex set of potential results e , and ex denotes the variable x , which is not odr-used ex (3.2)
the value contained in the reference object is not available .
I think our answer is whether *a satisfies the second point of the marker. I had a problem analyzing this state, so I'm not sure.