It's because undefined behavior can have unexpected results, including appearing to work.
Anything can happen, this is undefined behavior. What probably actually does happen is that B::c() uses the location where B::x would have been stored in a B instance, right after1 the A subobject. And it overwrites memory belonging to some other object. In your case, the value was previously 0 and became 1, but it could have been whatever value was put there by the real owner of that location.
(1) If the compiler implements the empty base class optimization, B::x and the B::A subobject could actually overlap.
If you're asking why the compiler doesn't prevent it, it's because you've overridden type checking by using a static_cast. Of all the casts, only dynamic_cast pays any attention to the true type of the object, and even that is easy to break.
You're composing two operations which are well-defined in a very unsafe way.
- The compiler can't stop you from casting an
A* to a B*, even when it knows there is no B object, because that B* is perfectly useful for the solitary purpose of casting back again. - And it can't stop you from using a
B* to access B members.
The problem is that you used this "fake" B* for something other than casting back to its true type.