04 April 2009

Refresh your Pointers knowledge

This little piece of literature will let us prevent a category of defects related to pointers. But first, let us take a small test. It will help us to decide if the entire snippet  is really worth reading. So here are the questions.

Consider, following are some of the declarations in a piece of code.
     int x , y, *p, **pp ;
   int *array[5], arr[5];
   int *f(int), **g(int);


Now, for which of the following eight statements the compiler will complain and for which it will not complain?
Let us try the test; check if we can hit it right in less than sixty seconds!
1.    x = y;
2.    *p = array [0];
3.    *p = **pp;
4.    x = f (4);
5.    p = *g (3);
6.    array [0] = arr[0];
7.    arr [0] = * array [1];
8.    array [5] = **g (3);


Here are the answers. For all odd number statements 1,3,5… .. the compiler will not complain.
For all even number statements 2,4,6… . The compiler will complain.

Let us now figure out quickly some of the mistakes we saw earlier. The way to find  what works and what does not, is rather simple. That is because, we can consider a C/C++ declarations as an equation with an “=” sign, across which you can move the stars!

Let's hold on! We will see what we meant above

Let us consider the declaration  int * x;

Let's imagine an "equal to" sign in between as follows

     int = * x ; /* this one tells you that *x is int */

We can move the star across the “=” sign, as shown here:

     int * = x ; /* this one tells that x is an integer pointer or a
pointer to an integer*/


One more example will make things clearer.

     int ** y

Let's imagine it as:

     int = **y   (this means  **y is an integer).


After moving one star across:

     int * = *y ( this means that *y is an integer pointer).

After moving one more star across:
     int ** = y,  this means that y is an integer pointer pointer.



Now , let us combine the above two examples
      In the first example we saw  *x  is an integer
     In the second example we saw that  **y  is also an integer.

So, the compiler will not complain, if we write
     *x = **y
          or
     **y = *x

Similarly,
     x = * y   is also ok with the compiler because both the sides are
int *.

By now we have seen, how to quickly find what will work and what will not work by  MOVING THE STARS!
It is a good idea to have a look at the declarations for minimizing related defects.

Let us go back to the quiz questions we discussed earlier. We will go through the answers quickly by using this  MOVING THE STARS! method.

We have copied and pasted the declarations over here for easy reference:
     int x , y, *p, **pp ;
     int *array[5], arr[5];
     int *f(int), **g(int);

1.    x = y  is correct, because both sides are int
2.    *p = array [0] is wrong, because LHS is int but RHS is  int *
3.    *p = **pp    is correct because both sides are int.
4.    x = f (4) is wrong because LHS is  int and RHS is int *.
5.    p= *g (3) is correct because both sides are int *
6.    array [0] = arr [0] is wrong because LHS is int *  but RHS is  int.
7.    arr [0] = * array [1]   is correct, because both sides are  int.
8.    array [5] = ** g (3) is wrong, because LHS is  int*  while RHS is int.


Experience shows that regularly using this little trick helps in writing as well as reading code faster.
Of course, it also helps us in reducing mistakes.

No comments: