Friday, February 6, 2015

C Pointers in a Simple English

Everyday Analogy

What is a pointer?

A pointer is a 'piece of paper' which stores the 'phone no' of a 'target' object .
Using the pointer we can access the target.
Since we can easily change the target, we can create programs which don't need to know what variable/object they're operating on. They just operate on the variable indirectly through the pointer and don't care what the target is

Variables are like trees, they're rooted to one place
Pointers are like cheetahs, they're agile and dangerous.

TODO : Replace the kludgy diagram below with a scanned proper hand-drawn version.

Imagine a table with rows and columns, let's say this represents a "logical RAM".
Each cell can store data. So each cell can act as a variable.
Some of these variables could store locations of other cells instead of just number values.

So the cells are numbered left-to-right and top-to-bottom from 1-12 in the figure below:


So the 3rd cell stores the value 150 in it. And the 11th cell stores the value 200 in it.
So the 7th cell stores the address '3' to point to the 3rd memory cell (containing the value 150 in it).
And the the 10th cell stores the address '11' to point to the 11th memory cell (containing the value 200 in it).

Everyday Analogies:

A) Telephone Number Analogy :

We regularly use pointers in everyday life when we use telephone numbers.
 [Note :
  a)Telephone no.s give 2-way access whereas a pointer gives only 1-way access.
  b)Usually the no. of links is 1 to 3 in an access path.
 ]

Find any Person using your Friend Network (a la 6 degrees of separation):

Let us say Tom wants to tell his friend something important.
He can either physically go and talk to him or he can phone him.

Lets assume Tom phones Jerry.
   Tom ---> Jerry

Tom doesn't have Jerry's no. Tom calls up 1 to get Jerry's no.
   Tom ---> 1 ---> Jerry

Tom follows the "Six Degrees of Separation Rule" as he knows that someone in a path going outward will know Jerry's no.
   Tom ---> 1 ---> 2 ---> .... ---> N ---> Jerry

Here Tom calls Jerry by
 a) Firstly getting the contact no. directly or indirectly from 'a friend-of-a-friend-of-a-friend'.
 b) Secondly Dialling the number.

B) Links of a Chain : 

Here the intermediate links of the chain can change the destination similar to an operator diverting your call to
the concerned person in an organisation.

Say Tom wants some info (from Jerry), but N on the path knows that Mickey is a better source of info and gives Mickey's number instead.

 a)Original path:
   Tom ---> 1 ---> 2 --->...N ---> Jerry

 b)Redirection:
   Tom ---> 1 ---> 2 --->...N ---> Mortimer

We can remove a single link from anywhere in the chain and re-create the (slightly smaller) chain by reattaching the links near the break in the chain. There is a minimal cost of inserting new links or removing existing links in the chain. This is exactly the property which allows efficient linked lists and other data-structures to be used without being stuck with unwieldy arrays.
It takes a lot of copying to cover up the "hole" in an array if we need to delete or insert at the front or middle.
But pointers just require reassigning the links fix the "break" in the chain.

C) Train Shunting :

This is similar to shifting tracks for a train, we can easily divert the train to whatever track by using the shunting mechanism.

D) Postal Address :

Though not as precise and neat as the telephone number analogy you can think of a pointer variable as an envelope with the address of a person on a paper inside.

When do we use Pointers?

 a)When we want to randomly point to and access different areas of memory (say a sequence of objects).
 b) Access a specific memory location. (accessing a port or a vdu buffer)
 c) Create an anonymous object.
 d) Save our position in a sequence.
 e) Avoid needless copying/moving of data items in a data-structure by just adjusting few pointers.

A pointer can point somewhere (an object) or anywhere (an address).
 It can be repositioned to point elsewhere.

 Access the object contents by location (Like voodoo)
 Re-target
 Insulate knowledge of identity of target object. (Bearer Cheque, Lottery winner)
 Anonymous objects (using new or malloc )
 Iterating over a Sequence

  ptrvar = &Object1;    //targeting the pointer
  ptrvar           Object1
 [ 1000 ] -----> [........] location 1000

  ptrvar =  &Object2;    //retargeting the pointer
 [ 2000 ] -----> [........] location 2000


We need pointers to keep track of our position as we access different locations.
Everyday usage :
The index finger 'points' to our current location in a phone-directory as we rapidly scan through the entries.
Website URLs, Postbox numbers or Postal addresses.

 We want to call up all people with the prefix 2375XXXX we just start at 23750000 and then
 keep adding 1 to the no. till we reach 23759999
 We could call up all people with 2375XXXY where Y is an even no. and so on.
 We can randomly dial any no. without knowing the person at the other end (anonymous object)

How do we use Pointers?

a) Example code to understand Pointers : C Source Code/Pointers 

b) C Code to traverse and insert a node in a linked-list:
 typedef struct list {
   int data;
   struct list *next;
 }List;

 void printlist(List *first)
 {
  List *tmp;
  for(tmp = first; tmp != NULL ; tmp = tmp->next ) { // step through the sequence
      printf("%d", tmp->data);
  }
  return ; 
 }

 int main()
 {
  int x=1,y=2,z=0;
  int num[3] = { 1, 2, 0 };
  List *head = makelist();    //returns an anonymous list of objects ->[10]->[20]->[30]->null
 
  add(&x,&y,&z);            // z = 3
  add(&num[0],&num[1],&num[2]);        // num[ 1, 2, 3]
  printlist(head);

  return 0;
 }

 void add(int *a,int *b,int *c)
 {
  return *c = *a + *b;
 }
===================================================================

Location access using Pointer or Array Notation:


int iarr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //Note : arrays are 0-indexed in C
int * iptr = &iarr[0];   //store address of 1st location of array in iptr
*iptr = 42;  //get the address from envelope using star operator, go to location and assign '42' number

iptr[0] = iptr[9];  // read last integer of array and assign to 1st cell of array (using array notation)
*(iptr+0) = *(iptr+9);  //Same as previous code we're just using pointer notation (instead of array notation).


See Also : 
  1. Ted Jensen C Pointer Tutorial : http://pweb.netcom.com/~tjensen/ptr/pointers.htm
  2. The 5 Minute Guide to C Pointers : http://denniskubes.com/2012/08/16/the-5-minute-guide-to-c-pointers
  3. "Understanding Pointers in C" by Yeshawant Kanetkar (BPB Publications).
  4. "Understanding C by Learning Assembly" : https://www.hackerschool.com/blog/7-understanding-c-by-learning-assemblyhttps://www.hackerschool.com/blog/7-understanding-c-by-learning-assembly
  5. Learning C with GDB : https://www.hackerschool.com/blog/5-learning-c-with-gdb
  6. Super Tutorial on Linux Memory Management : http://www.linux-tutorial.info/modules.php?name=MContent&pageid=261
  7. Internals of C++ and Unix : http://techtalkies.blogspot.com/2007/07/good-articles-on-internals-of-c-and.html