Setup
Given this user-defined type:
struct T
{
static int x;
int y;
T() : y(38);
};
and the requisite definition placed somewhere useful:
int T::x = 42;
the following is the canonical way to stream the int
's value to stdout:
std::cout << T::x;
Control
Meanwhile, the following is (of course) invalid due to an instance of T
not existing:
T* ptr = NULL; // same if left uninitialised
std::cout << ptr->y;
Question
Now consider the horrid and evil and bad following code:
T* ptr = NULL;
std::cout << ptr->x; // remember, x is static
Dereferencing ptr
is invalid, as stated above. Even though no physical memory dereference takes place here, I believe that it still counts as one, making the above code UB. Or... does it?
14882:2003 5.2.5/3 states explicitly that a->b
is converted to (*(a)).b
, and that:
The postfix expression before the dot or arrow is evaluated; This evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the id-expression denotes a static member.
But it's not clear whether "evaluation" here involves an actual dereference. In fact neither 14882:2003 nor n3035 seem to explicitly say either way whether the pointer-expression has to evaluate to a pointer to a valid instance when dealing with static members.
My question is, just how invalid is this? Is it really specifically prohibited by the standard (even though there's no physical dereference), or is it just a quirk of the language that we can probably get away with? And even if it is prohibited, to what extent might we expect GCC/MSVC/Clang to treat it safely anyway?
My g++ 4.4 appeared to produce code that never attempts to push the [invalid] this
pointer onto the stack, with optimisations turned off.
BTW If T
were polymorphic then that would not affect this, as static members cannot be virtual.