I remember the C vs. C++ enums were already discussed a while ago. In C, there is no check whatsoever. In C++, there is.
So in C, there is no way of doing this. In C++, you can use enums - assigning values not in the enum in C++ should yield an error.
For state machines, obviously in C you can use a fallback case - 'default' - which would then handle the error if it ever gets there. But it's only a run-time check. I can't see a simple way of checking that at compile time.
But as said above, what's the probability of this being a real problem? When dealing with state machines, as in your example, do you think the probability of assigning a value (here, a state, for instance) not in the set of handled states would be any higher than just assigning the wrong state (in the right set of handled states)? It is doubtful. And in any case, a check at run time looks like a good idea.
Now for the more general case of restricted range variables, few languages really allow you to define static types with restricted ranges that are checked at compile time. One of them is ADA. C++ is better than C here, but only for the limited case of enums, which is better than nothing but is still very lacking.