Your question is a basic question, but one that every new C-programmer wrestles with and is fundamental to understanding C. Understanding pointers. While they are easy to understand once you understand them, getting to that point can be frustrating based on the way the information is presented in many books or tutorials.
Pointer Basics
A pointer is simply a normal variable that holds the address of something else as its value. In other words, a pointer points to the address where something else can be found. Where you normally think of a variable holding an immediate values, such as int n = 260;
, a pointer (e.g. int *p = &n;
) would simply hold the address where 260
is stored in memory.
If you need to access the value stored at the memory address pointed to by p
, you dereference p
using the unary '*'
operator, (e.g. int j = *p;
will initialize j = 260
).
If you want to obtain a variables address in memory, you use the &
(address of) operator. If you need to pass a variable as a pointer, you simply provide the address of the variable as a parameter.
Since p
points to the address where 260
is stored, if you change that value at that address (e.g. *p = 41;
) 41
is now stored at the address where 260
was before. Since p
points to the address of n
and you have changed the value at that address, n
now equals 41
. However j
resides in another memory location and its value was set before you changed the value at the address for n
, the value for j
remains 260
.
Pointer Arithmetic
Pointer arithmetic works the same way regardless of the type of object pointed to because the type
of the pointer controls the pointer arithmetic, e.g. with a char *
pointer, pointer+1
points to the next byte (next char
), for an int *
pointer (normal 4-byte integer), pointer+1
will point to the next int
at an offset 4-bytes after pointer
. (so a pointer, is just a pointer.... where arithmetic is automatically handled by the type
)
In your case you create a second pointer of a different type char *pp = (char*)p;
. The pointer pp
now also holds the address of n
but it is interpreted at type char
on access instead of type int
.
The C standard prohibits access of a value stored at an address though a pointer of a different type. C11 Standard - §6.5 Expressions (p6,7) (known as the strict-aliasing rule). There are exceptions to the rule. One exception (the last point) is that any value may be accessed through a pointer of char
type.
What Happens to the Value of n In Your Case?
When you assign:
*pp = 0;
you storing the single-byte 0
(or 00000000
in binary) to the memory location held by pp
. Here is where endianess (little-endian, big-endian) come into play. Recall, for little-endian computers (just about all x86 and x86_64 IBM-PC clone type boxes), the values are stored in memory with the Least-Significant Byte first. (big-endian stores values with the Most-Significan Byte first). So your original value of n
(10000100
in binary) is stored in memory on a little-endian box as
n (little endian) : 00000100-00000001-00000000-00000000 (260)
^
|
p (type int)
The character pointer pp
is assigned the address held by p
, so both p
and pp
, hold the same address (the difference being one is a pointer to int
the other a pointer to char
:
n (little endian) : 00000100-00000001-00000000-00000000 (260)
^
|
p (type int)
pp (type char)
When you dereference pp
(e.g. *pp
) and assign the value zero (e.g. *pp = 0;
), you overwrite the first byte of n
in memory with zero. After the assignment, you now have:
n (little endian) : 00000000-00000001-00000000-00000000 (256)
^
|
p (type int)
pp (type char)
Which is the binary value 100000000
, (256
or hex 0x0100
) and what your code outputs for the value of n
. Ask yourself this, if the computer you were using was big-endian, what would be resulting value have been?
Let me know if you have any further questions.