The expressions x++ and ++x have both a result (value) and a side effect.
The result of the expression x++ is the current value of x. The side effect is that the contents of x are incremented by 1.
The result of the expression ++x is the current value of x plus 1. The side effect is the same as above.
Note that the side effect doesn't have to be applied immediately after the expression is evaluated; it only has to be applied before the next sequence point. For example, given the code
x = 1;
y = 2;
z = ++x + y++;
there's no guarantee that the contents of x will be modified before the expression y++ is evaluated, or even before the result of ++x + y++ is assigned to z (neither the = nor + operators introduce a sequence point). The expression ++x evaluates to 2, but it's possible that the variable x may not contain the value 2 until after z has been assigned.
It's important to remember that the behavior of expressions like x++ + x++ is explicitly undefined by the language standard; there's no (good) way to predict what the result of the expression will be, or what value x will contain after it's been evaluated.
Postfix operators have a higher precedence than unary operators, so expressions like *p++ are parsed as *(p++) (i.e., you're applying the * operator to the result of the expression p++). Again, the result of the expression p++ is the current value of p, so while (*p++=*q++); doesn't skip the first element.
Note that the operand to the autoincrement/decrement operators must be an lvalue (essentially, an expression that refers to a memory location such that the memory can be read or modified). The result of the expression x++ or ++x is not an lvalue, so you can't write things like ++x++ or (x++)++ or ++(++x). You could write something like ++(*p++) (p++ is not an lvalue, but *p++ is), although that would probably get you slapped by anyone reading your code.