A pointer is, basically, an address. Think about a pointer as an address label, and the value as the actual house. You can use the label to find the house, but the label isn't a house.
int *ptr; // declares a pointer to an int
So ptr is, essentially, a memory address. (It's possible that the C spec doesn't actually specify that it's an address, but bear with me).
int i = 5; // create a local int.
Declares an integer on the stack, and sets the value of it to 5. The address of i is somewhere in the stack space.
Let's look at one intermediate step before we go on. This probably wouldn't compile, and if it did, wouldn't actually do anything.
&i;
What this expression does is return the address of the variable i. It's the location of i in memory - the address of an integer.
And one last one...
*ptr;
Again, this probably wouldn't actually do anything, it's just an expression. But, what it does is dereference the pointer - it refers to the actual int located at the address contained in ptr.
Okay, so let's take a look at a few things that we can do.
ptr = i;
This doesn't do anything, at least anything we want to do. Probably won't compile, but I haven't checked it out. It doesn't do anything because it assigns an integer to the address of an integer. That's like sending a box through the post office to an address label - you actually want it to go to the house!
i = ptr;
Okay, this is the same thing as the last one, but in reverse. Following our analogy, this is trying to turn a house into a label!
*ptr = i;
Here we've dereferenced the pointer, and assigned the value of i to it. Dereferencing a pointer is essentially like using the label to drive to the house. Once we're there, we can do things to the actual house. This works because a dereferenced int pointer is an int, and an int is also an int.
ptr = &i;
This works too. &i basically makes a new label for the house 'i'. Since we have a pointer on both sides, we can assign one to the other. This is basically copying the address label for i to the address label called ptr.
*ptr = &i;
This doesn't make sense. We've started with two different things, and converted each into the other! Now we're trying to assign a label to a house, whereas before we were assigning a house to an address label.