There are some subtle problems with the model as explained in this article. If you use this as your mental model, you will probably run afoul of undefined behavior without realizing it.
If you read the C standard, you'll notice it doesn't talk much about "memory" (the word only appears 13 times in C99); it mostly talks about "objects" (mentioned 735 times in C99). These objects aren't OO-objects -- obviously C doesn't have OOP built in -- but rather all the basic types like int, float, struct, etc are objects. When you declare a variable like "int x", you are creating an object.
C's aliasing rules dictate that you can only access an object via a pointer of that object's actual type. This is why it is dangerous to think of the assignment operator as a simple memory-copying operation. If assignment were a simple memcpy, you could do something like this:
int x = 5;
// BAD: undefined behavior, violates aliasing.
short y = *(short*)&x;
If a variable were just a memory address and assignment were just a memory copy, this would be a valid operation. But the right way to think of it is that a variable is a
storage object whose address can be taken, and and a dereference is an operation that reads a storage object.
A pointer isn't a generic memory-reading facility, it must actually point to a valid storage object of the pointer's type (or to NULL).
If you do want to read and write arbitrary objects in memory, you can always use memcpy():
int x = 5;
short y;
// This is fine, and smart C compilers optimize away the
// function call.
memcpy(&y, &x, sizeof(y));