The first step in understanding pointers is visualizing what they represent at the machine level. In most modern computers, main memory is divided into bytes. with each byte capable of storing eight bits of information.
Each byte has a unique address to distinguish it from the other bytes in memory. If there are n bytes in memory, we can think of addresses as numbers that range from 0 to n - I .
An executable program consists of both code (machine instructions corresponding to statements in the original C program) and data (variables in the original program). Each variable in the program occupies one or more bytes of memory;
Here's where pointers come in. Although addresses are represented by numbers, their range of values may differ from that of integers, so we can't necessarily store them in ordinary integer variables. We can, however, store them in special pointer variables. When we store the address of a variable i in the pointer variable p. we say that p "points to" i. In other words, a pointer is nothing more than an address, and a pointer variable is just a variable that can store an address.
The Address and Indirection Operators
C provides a pair of operators designed specifically for use with pointers. To find the address of a variable, we use the & (address) operator. If x is a variable, then &x is the address of x in memory. To gain access to the object that a pointer points to, we use the * (indirection) operator. If p is a pointer, then *p represents the object to which p currently points.
The Address Operator
Declaring a pointer variable sets aside space for a pointer but doesn't make it point to an object:
int *p; /* points nowhere in particular */
It's crucial to initialize p before we use it. One way to initialize a pointer variable is to assign it the address of some variable—or, more generally, lvalue—using the & operator:
int i, *p;
p = &i;
By assigning the address of i to the variable p, this statement makes p point to i.