It should seem weird. It isn't normal to try and hack C's type system. But when you get down to how C really works, there isn't much stopping you from assigning to an int by pretending it's a structure.
C99 requires that objects be represented by a contiguous sequence of bytes.
Further down, the standard says:
This makes it possible to do all sorts of wonderful things. For instance, any object can be punned into a sequence of unsigned chars --
(unsigned char*)&obj -- this is the reason that memcpy can work.
Let's simplify shiroaisu's example for discussion:
Code:
struct T {
int a;
};
void foo(void *pointer)
{
struct T *t = pointer;
t->a = 10;
}
int main()
{
int x = 1;
foo(&x);
}
Now, does the program exhibit undefined behavior or not? It does. Since the object representations of an integer and a struct T containing an integer do not have to be the same, there are a bunch of question marks around this. The program can appear to work correctly when the compiler decides that the way to represent the structure T is the same way to represent other integers. (After all, where exactly is the difference in bits.) However, it is also valid to allocate space for the integer and then some padding. If you're lucky, the computer would segfault in that case. A standards conforming compiler could try to access the padding, which would probably cause a crash.
The bad thing about undefined behavior is that tons of programs invoking it appear to work. Crashes are a good thing, a sign something is probably a mistake.
In the same vein, void pointers/casts are bad, for silently allowing things like this.