Part 8 - Pointers
-----------------
Welcome to Part 8 of my tutorial.  In this section we will be dealing
with a very important subject.  Pointers.
Now, pointers are so important that there are many resources and
tutorials, like this one, dealing only with pointers.  If this tutorial
doesn't help you understand pointers, don't worry.  Search the internet
and you can find many more examples and tutorials of pointers.  I like
this one myself: http://pweb.netcom.com/~tjensen/ptr/pointers.htm but I
am sure there are others out there.
Let's continue.  You might now be wondering what this thing, called a
pointer, is.  In short, a pointer is a variable that contains the
memory address of another variable.  Now you might be wondering; "So?
What good is that?"  The reasons become clearer later on in this tutor.
First of all, a pointer needs to be declared, just like all variables.
We do this like so:
  int *Num;     /* A pointer to type int */
As you can see, this is the same method we use to declare all variables.
The only difference is that we stuck a "*" onto the front of the name.
The "*" character tells the compiler that this variable is a pointer.
A pointer can be defined as any of C's data types; int, float, long,
char etc.  In case you're wondering, the "*", when used in front of a
variable, as we did above, has a name.  It is called the "indirection
operator" or "dereferencing operator".  That isn't terribly important
for now, but if you can remember that, then great.  You'll see why it
has that name shortly.  The name of our variable is "Num" not "*Num".
This is important.  If you try to print "Num", you'll get a different
answer than you would if you tried to print "*Num".
Now that we have a variable defined, we have to initialize it.  Just
like you have to initialize all variables.  (Well, except for variables
that are defined outside of all functions.  They are initialized to 0).
A pointer is very lonely without an address to point to.  So let's give
it one.  This is one way to do it.
  int x = 0;  /* Plain old integer initialized to 0. */
  int *Num;   /* A pointer to int */
  Num = &x;   /* Put the address of "x" in Num. */
We have a new operator to discuss.  The Address-of operator.  The
Address-of operator is the "&" symbol.  Why is it called address-of?
Because, the "&" symbol, when placed in front of a variable, will
retrieve that variables address in memory.  Neat eh?  What we did above
is copy the address of "x" into "Num".  Therefore, we just made
"Num" point-to "x".  You can now change the value of "x" by using the
pointer variable "Num".  How?  Like this:
  *Num = 99;
The above will place the number 99 in the address pointed to by "Num".
Since "Num" points to the address of "x", then x = 99;
To quickly sum things up here:  "*Num" and "x" both refer to the
contents of "x".  "Num" and "&x" both refer to the address of "x".
Let's now take a look at a program to explain everything more fully.
/*------------------------------------------------------------
 Program:       PTREXAMP.C
 Author:        CORVUS
 Date:          Sept. 10, 2001
 Description:   This program gives examples of
                pointer variables.
 -----------------------------------------------------------*/
#include<stdio.h>
int main(void)
{
  int x = 99;   /* Let x = 99 */
  int *Num;    /* A pointer to int */
  Num = &x;    /* Make Num point to x. */
  /* Direct and Indirect access of x */
  printf("Direct access using \"x\": %d",x);
  printf("\n");
  printf("Indirect Access using \"*Num\": %d",*Num);
  printf("\n\n");
  /* Display addresses */
  printf("The Address of \"x\" is: %p", &x);
  printf("\n");
  printf("The address of \"x\" using \"Num\" is: %p", Num);
  return 0;
}
My output was:
  Direct access using "x": 99
  Indirect access using "*Num": 99
  The Address of "x" is: 11D4:1000
  The address of "x" using "Num" is: 11D4:1000
The addresses that you get will (probably) be different from these,
especially under a 32 bit operating system that uses flat memory
addressing.
Let's discuss pointers and arrays.  It just so happens that you can use
pointers to move through arrays.  Let's look at an example to see what
I mean:
  int array[] = {2,4,6,8,10,12}
As you might recall from my earlier tutor about arrays, you can access
each element like so:  printf("array[2] = %d", array[2]).  This would
display the number 6.  You can access any element in this way.  There
is however an alternative.  Pointers.  Here's an example:
  int *element;
  element = &array[0];  /* Make element point to the 1st
                           element of our array. */
Now that you have "element" pointing to the first element of the array,
you can now go through the array using pointers.  To go through the
array, you do some pointer incrementing.  Let's assume we are at the
first element of our array.  To get to the second element, you can type:
  element++;  /* move to the next element in array */
Using the same method, you can decrement like so:
  element--;  /* Move back one element in the array */
Please do some bounds checking to make sure you aren't going outside
the size of the array.  I believe (if memory serves) that this will
cause `UB'.  Also known as Undefined Behavior.  Which is a Bad Thing.
An example program will help demonstrate the use of what can be called,
"Pointer Arithmetic".
/*--------------------------------------------------------------
 Program:       PTRARRAY.C
 Author:        CORVUS
 Date:          Sept. 10, 2001
 Description:   This program gives an example of incrementing
                pointers to move through an array.
 -------------------------------------------------------------*/
#include<stdio.h>
#define MAX  6
int main(void)
{
  int array[MAX] = {2,4,6,8,10,12};  /* Declare and initialize an
                                        array of integers. */
  int *element;     /* A pointer to an int */
  int i;            /* Loop counter */
  element = &array[0];  /* Initialize the pointer */
  /* Display the array elements. */
  for (i = 0; i < MAX; i++)
    printf("Element %d is:\t%d\n", i, *element++);
  return 0;
}
What we are doing in the above program is declaring and array of ints.
We also initialize the array with values.  We also make a pointer to an
int called "*element".  We will use this to point at the different
elements of our array.
We actually don't need word MAX inside our array, since we have already
pre-initialized it and it's value has already been set to 6 because of
it.  I placed it there, just to show you that you can declare the size 
of an array like so.
Since our pointer is still not initialized, we must initialize it.  To
do that, we make it point to the address of the first element in our
array.
We then set up a loop to display the elements in the array.  In the
body of the loop is our printf statement that displays the output.
Inside the printf statement we display the contents of a certain
element by calling "*element".  This by itself will only display the
first element over and over again (because that is where we made it
point to originally).  To fix this problem we append a "++" to the
variable so as to move it to the next array element.
On a side note, you can also use: 
sizeof(array) / sizeof(*array) inside the "for" loop, instead of using
"MAX" that we defined as 6 earlier.
So there you have some examples of pointers.  Pointers come in very
useful when you want to dynamically allocate memory.  We will discuss
dynamic memory allocation in later parts of this tutorial.
This is a very basic introduction to pointers.  We will continue our
use of pointers in the next part, where I will discuss strings and
how you can allocate memory using malloc() and family.
Now on to Part 9.