Earlier quoted context omitted.
That's certainly true if you mix accesses to the same object via volatile and non-volatile pointers. It's even explicitly undefined in the standard. (C99 §6.7.3/5). [while in practice it will work most of the time] But if you always access a certain object through casts to ((volatile )&x), I don't see how this should be different than accesses to a globally declared "volatile x" variable, as pointers are guaranteed t…
The key text is in C99 §6.7.4: "An object that has volatile-qualified type...". Note that this does not say "An object accessed via a pointer to a volatile-qualified type": What matters is the type of the underlying object, i.e., how it is originally defined.
That being said...
§6.5.3.1/4 The unary * operator denotes indirection. (...) the result is an lvalue designating the object.
So, I believe that there will be no difference in access to something declared as
volatile X v;
v = ...;
and X v;
*((volatile X*)&v) = ...;
if the access to v will always be performed through such a cast, as ((volatile..)) will always denote the same "volatile" X object stored in v, independent of the fact that storage to the volatile X object is allocated in a "nonvolatile" X object.