I read the entire FAQ for pointers, and I'm still stuck

. What I (think) I understand is that when you declare pointer such as:
int *ptr;
Then that points the address of a variable and not the value inside the address. What I'm not understanding is, what do these do:
Here, ptr is a variable. Its value (once you give it one) will
not be an int, but a value that locates an int somewhere else. By
way of analogy, ptr is a telephone number and the thing it points at
is the telephone.
Like most operators, the unary & operator produces a value. The
value it produces is a pointer to its operand, so &ptr is a value
that points at the variable ptr.
... which is itself a pointer, so maybe we're getting a little
deep for beginners. Let's go back to shallower water for a while:
int foo = 42;
int bar = 56;
int *ptr;
Here we have two int variables, each with its own integer value.
We've also got a pointer variable capable of pointing at ints, but
it hasn't been given a value yet (just as in `int x;' the x has
not yet been given a value). So, let's assign a value:
ptr = &foo;
The &foo part produces a pointer value aiming at the variable
foo, and then we store that value in ptr, making ptr point at foo.
Later on, we might change our mind:
ptr = &bar;
Again &bar produces a pointer value, this one aimed at bar, and we
store that value in ptr. Now ptr points at bar instead of at foo.
Why is this useful? Because we can do things like
printf("The Answer is %d\n", *ptr);
.... without caring whether ptr is aimed at foo or at bar or perhaps
at some other int altogether. The prefix * operator looks at its
operand -- a pointer -- finds out what it points at, and delivers
the value of the pointed-at thing. By using ptr, we can make this
single printf() call able to print the value of any int variable in
the program: We just aim ptr at it, and execute the call.
We can also use this on the left-hand side of an assignment:
*ptr = -17;
This stores minus seventeen in ... well, in whatever ptr is
aimed at when the statement is executed. We don't have to write
different assignments for foo and for bar, the same assignment
works for either of them -- or for anything else we've aimed ptr at.
It's useful to have a special pointer value that means "I'm
not pointing at anything whatsoever." That's what a null pointer
is for; the FAQ goes into some detail on how they're used.
3.ptr++ vs ++ptr vs (*ptr)++ etc...
When the pointer's target variable is not isolated but is one
element of an array, it makes sense to do arithmetic on the pointer
values: "Whatever you're pointing at, find the next-door neighbor."
You can move forward and back in single steps with ++ and --, or
in larger steps by adding/subtracting bigger integers.
This is a special case: A pointer to something whose nature
is not stated. It might be pointing at an int, or at a char, or
at a float, or at anything at all. That flexibility makes it
useful for writing "generic" code that can operate on many different
kinds of data, rather than writing separate routines for int, char,
float, and so on.
The flexibility comes at a price: Since the type of the target
is unknown, you can't use *ptr to fetch a value from it, nor to store
a value in it. Nor can you do arithmetic on the pointer, since you
don't know how big a step takes you from one unknown-type variable to
its neighbors. You can pass arbitrary pointer values around in your
program by using void*, but you can't actually do much with them
until you say "Aha: I happen to know that the target is a double,
so I'll convert my void* to a double* and proceed."
... which brings up another part of the price: Loss of type
safety. Since you can convert any kind of data pointer to void*
easily, and then convert a void* to a data pointer again equally
easily, it's absurdly easy to get the types wrong. You start with
&foo (an int* from an earlier example), convert it to void*, then
arrive at the "Aha" moment and convert the void* to a double*. You
are now In Trouble, because you're trying to do double-ish things
on an int. It's like packing all the picnic lunches in identical
paper bags, then giving the ham and Swiss on whole wheat to the
vegetarian Jewish celiac sufferer because all the bags looked alike.
Be watchful always, and be extra watchful when converting pointers
from one type to another.