Sunday, March 18, 2007

Pointers in C

Pointers

Consider that we have an int called y. Its address could be represented by the symbol &i. If the pointer is to be stored as a variable, it should be stored like this.

int *pi = &y;

int * is the notation for a pointer to an int. & is the operator which returns the address of its argument. When it is used, as in &i we say it is referencing i.

The opposite operator, which gives the value at the end of the pointer is *. An example of use, known as de-referencing pi, would be

y = *py;

Take care not to confuse the many uses of the * sign; Multiplication, pointer declaration and pointer de-referencing.

Let us see an example. The following function jobs takes two arguments, x is an int while y is a pointer to int. It changes both values.

jobs(int x, int *y)
{ printf("Starting job : x = %d, y = %d\n", x, *y);
x ++;
(*y)++;
printf("Finishing job : x = %d, y = %d\n", x, *y);
}


since y is a pointer, we must de-reference it before incrementing its value.A very simple program to call this function might be as follows.

main()
{

int i = 0;
int j = 0;
printf("Starting main : i = %d, j = %d\n", x, y);
printf("Calling jobs now\n");.
jobs(i, &j);
printf("Returned from jobs\n");
printf("Finishing main : i = %d, j = %d\n", x, y);
}


Note here how a pointer to int is created using the & operator within the call jobs(i, &j);.The result of running the program will look like this.

Starting main : i = 0 ,j = 0
Calling jobs now
Starting jobs: x = 0, y = 0
Finishing jobs: x = 1, y = 1
Returned from jobs
Finishing main : i = 0, j = 1


After the return from the function jobs the value of i is unchanged while j, which was passed as a pointer, has changed.

To summarise, if you wish to use arguments to modify the value of variables from a function, these arguments must be passed as pointers, and de-referenced within the function.

Where the value of an argument isn't modified, the value can be passed without any worries about pointers.
.....................................................................



Arrays and Pointers

An array is actually a pointer to the 0th element of the array. Dereferencing the array name will give the 0th element. This gives us a range of equivalent notations for array access. In the following examples, arr is an array.

Array Access Pointer Equivalent
arr[0] *arr
arr[n] *(arr + n)

Differences between arrays and pointers.

The array is treated as a constant in the function where it is declared. This means that we can modify the values in the array, but not the array itself, so statements like arr ++ are illegal, but arr[n] ++ is legal.

Since an array is like a pointer, we can pass an array to a function, and modify elements of that array without having to worry about referencing and de-referencing. Since the array is implemented as a hidden pointer, all the difficult stuff gets done automatically.

A function which expects to be passed an array can declare that parameter in one of two ways.

int arr[]; or int *arr;

Either of these definitions is independent of the size of the array being passed.

This is met most frequently in the case of character strings, which are implemented as an array of type char.

This could be declared as char string[]; but is most frequently written as char *string;

In the same way, the argument vector argv is an array of strings which can be supplied to function main. It can be declared as one of the following.

char **argv; or char *argv[];

-----------------------------------------------------------------------------------------------------------------------


Recursive Functions

A recursive function is one which calls itself.

Recursive functions are useful in evaluating certain types of mathematical function. You may also encounter certain dynamic data structures such as linked lists or binary trees. Recursion is a very useful way of creating and accessing these structures.

Here is a recursive version of the Fibonacci function.

int fib(int num)
{
switch(num)
{
case 0:
return(0);
break;
case 1:
return(1);
break;
default: /*Recursive calls */
return(fib(num - 1) + fib(num - 2));
break;
}
}


In the above function fib is called inside the function itself with a condition.Care must be taken to define functions which will not call themselves indefinitely, otherwise your program will never finish.

Recursive functions are sometimes the simplest answer to a calculation. However there is always an alternative non-recursive solution available too. This will normally involve the use of a loop, and may lack the elegance of the recursive solution

No comments: