Values stored in memory are a set of '1's and '0's which by themselves do not mean anything. Datatypes are used for recognizing and interpreting what the values mean. So lets say, at a particular memory location, the data stored is the following set of bits ad infinitum: 01001010 ....
. By itself this data is meaningless.
A pointer (other than a void pointer) contains 2 pieces of information. It contains the starting position of a set of bytes, and the way in which the set of bits are to be interpreted. For details, you can see: http://en.wikipedia.org/wiki/C_data_types and references therein.
So if you have
a char *c
,
an short int *i
,
and a float *f
which look at the bits mentioned above, c
, i
, and f
are the same, but *c
takes the first 8 bits and interprets it in a certain way. So you can do things like printf('The character is %c', *c)
. On the other hand, *i
takes the first 16 bits and interprets it in a certain way. In this case, it will be meaningful to say, printf('The character is %d', *i)
. Again, for *f
, printf('The character is %f', *f)
is meaningful.
The real differences come when you do math with these. For example,
c++
advances the pointer by 1 byte,
i++
advanced it by 4 bytes,
and f++
advances it by 8 bytes.
More importantly, for
(*c)++
, (*i)++
, and (*f)++
the algorithm used for doing the addition is totally different.
In your question, when you do a casting from one pointer to another, you already know that the algorithm you are going to use for manipulating the bits present at that location will be easier if you interpret those bits as an unsigned char
rather than an unsigned int
. The same operatord +
, -
, etc will act differently depending upon what datatype the operators are looking at. If you have worked in Physics problems wherein doing a coordinate transformation has made the solution very simple, then this is the closest analog to that operation. You are transforming one problem into another that is easier to solve.