Pointers are just a variable whose purpose is to store an address.  An address is a location in your PC's memory and for 32 bit CPU's that address is a 32 bit number. 

A pointer can hold the address of any type of data you wish to reference.  Commonly used to hold the address of some allocated memory since you need to tell the system you are done with the memory at some point.

This may be old hat for some of you, so bear with me.  Allocating and freeing memory is something all programs do, and the terms may be confusing at first. 

INT *p;
p = NEW(INT, 1000);

Lets look at whats going on here.  First we are defining a pointer and telling the compiler it points to data of type INT.  Then we are asking the system for an address of a memory block we can use to store 1000 integers.

Memory isn't being created, it is just being reserved for you.  The system gives you an address at the beginning of a 4000 byte block of memory and marks it as belonging to your program, so no other program can access it.

Now we have an array, dynamically allocated, that we can use just like any other array.  With the one difference that it is just an address so we need to tell the compiler to dereference the pointer before accessing the array.

*p[10] = 100;

Stores the value of 100 into the 11th slot of the array (array indexes are zero based).  The '*' tells the compiler that 'p' is a pointer that contains the address we want to use, otherwise the compiler would use the address of 'p' itself.  That statement could also be expressed as:

*(int)(p + (4 * 10)) = 100;

Following along that is telling the compiler to add 4*10 to that address stored int 'p' and dereference it as an integer, finally storing 100 in that location.  10 is the slot in the array, 4 is the size of an integer.  Which is exactly what the compiler does when it sees *p[10]

After we are done with allocated memory we need to let the system know that it can safely let other processes use that memory.

delete p;

A confusing statement to new users.  You're not actually 'deleting' anything in the strictest sense of the word, you're not deleting the variable 'p', you're telling the compiler to give back the memory whose address is stored in 'p'.  The memory is still there of course, it is just marked as no longer being used by your program.

Code you can play with:

Code:
global sub main()
{
int *p;
p = new(int, 1000);
for( int x=0;x<1000;x++)
{
# *p = x;
//The above is equivelent to:
//*(int)(p + 4 * x) = x;
}
for(x = 0;x< 1000;x++)
{
writeln(using("####, ",*p
# ));
}
delete p;
while getkey() = "";
}

Allocated memory is not limited to simple arrays.  A structure, or UDT as it is called in other languages, is a convenient packaged for holding related data.  Lets say you're building a 3D application and want a point datatype that can hold x,y and z coordinates of a 3D drawining.  Commonly referred to as a vertex

Code:
struct vertex
{
float x;
float y;
float z;
}

And your drawing has 500 points.

vertex *pShip;
pShip = new(vertex,500);

Then you have a loading subroutine that loads the data from a disk file;

Code:
for(int x = 0; x < 500; x++)
{
#   *pShip.x = StrToNum(readln(file1));
  *pShip
# .y = StrToNum(readln(file1));
  *pShip
# .z = StrToNum(readln(file1));
}

Using pointers and allocated memory allows you to have any size data.



Speaking of logical I just finished the pointer handling syntax of Aurora.  Those that used pointers in Pro will appreciate the fact that Aurora allows typed pointers by definition as well as the old Pro way of assignment.

In Pro you had generic pointers, which is still allowed in Aurora

POINTER myptr;
INT b;
myptr = b;
...
*b = 122;

In the above code the pointer doesn't have a 'type' until the address of b is assigned to it.  Then it 'points to' and INT type.  While convenient for most it was confusing for anyone converting from other languages.  The other problem was passing a pointer to a subroutine..

SUB mysub(ptr as POINTER)
*ptr = 122;
...

Would generate an error because at that place in the code the type that 'ptr' pointed to was unknown.  In Pro I added the SETTYPE command to alleviate this, or you could use type casting.  In Aurora you can use C syntax for pointers now, which removes the need for typecasting or the use of SETTYPE. 

SUB mysub(int *ptr)
*ptr = 122;

...
