Some help with Pointers
 
CSCI 515 
 
This document contains a short bit of information quickly written regarding the concept, value, and uses of pointers.  NO guarantee
of it's perfect accuracy is given as this was typed very fast. And,this document has not yet been proof-read or even spell checked.. 
yet I wished to get it out to the current 515 students quickly.If one knows of someone that was not included in the initial 
distribution of this document, see what one can do to email or otherwise deliver it to him/her or them.
 
Also, one will likely not obtain full competency or understanding of this document's contents with one or even two readings - unless
one has read a good chapter or two on arrays in a text-book .. and some parts will not be clear even until possibly you are in the 520
class..  though all of this should be known by the end of 515.
 
Scan it, try to understand what you can, read other sources, ask for GA clarifications and understandings, and DO NOT MISS A SINGLE LECTURE 
and take good notes during lectures - especially those tied to the use of pointers in code.
 
An expert professional cs professor who uses code precisely as Dr. Creider does - will maximize execution speed and flexibility 
via the use of pointers not often found in common computer science texts.
 
For those reading this document who are in the 520 class, the accessing 
of structural objects via pointers using the -> denotation is beyond the scope of this document... at least at this time...  Expect possible
modifications to this document in the future as other graduate assistants or myself have time to improve it..  Your feed-back is a valuable
source of the type of improvements or re-organization that will provide  motivations for such improvements and modifications.
 
Learning about pointers is not actually required until the class begins to use them or they are initially discussed in lectures, yet as they 
represent a concept that is a bit challenging to those new to them, getting a head start on them can make a huge difference, so long as one
does not get behind on their non-pointer assignments and learning’s.
 
 
Pointer - A simple Definition:  
 
A pointer is a data type that is allowed to store (and only allowed to store) a memory address, which on today's current personal computers
would range from anywhere from 0 to 4gigabytes typically.  On larger or even advanced systems, this limit is obviously breached.
 
In many ways, it is that simple - and yet as one learns more about them and begins to use them in their implementation syntax code for
programs ... one can get sidetracked and lost if one does not keep such a simple definition in mind.  A pointer is nothing more than
a variable that can hold (and only can hold or store) a memory address.
 

Pointer Variable:

 

Key concept review:  A pointer variable holds the memory address of another memory location.  The other memory location can be a short, long, double, the offset 0 or start of an array, or even another pointer variable.

 

 
Pointer to Short
 
 
<< Pointer Variable >>                       << Short Variable >>
 
 
 
 
 
 

Note:  The content of the pointer variable is the same as the cell address of some short variable in the above simple diagram.
 
 
 
Pointer to Pointer
 
 
<< Pointer Variable >>   << Pointer Variable >>   << Short Variable >>
 
 
 
 
 
 

Note:  The content of the 1st pointer variable is the address of another pointer (the 2nd pointer depicted in the center).  The content of the 2nd pointer is the address of a short variable.  The content of the short variable is obviously a short variable.  In this case, it is storing the value 515.
 
 
 
 
 
 
So, what is the value or purpose of pointer variables?
 
1.           a critical value or purpose of pointers is flexibility.
2.           another value or purpose is an increase in execution speed in some cases.
 
 
As with other variables, a pointer has an associated name, but it's purpose is a bit different as we shall soon see.
 
Typically, with the C and Java programming languages, a memory address is when one is looking at the syntactical code is indirectly accessed 
via a name decided upon by the author or programmer who wrote the code or the code generator that created automated code.
 
short  x; x is the name of the variable which is of type short.
double z; z is the name of the variable which is of type double.
 
short* x; x is the name of the variable which is of type short*.
 
short* ??? - the * designates the variable as a pointer.
 
Short* - short pointer
long*  - long  pointer
double* - double pointer
char*   - char pointer
 
why not just use the word "pointer", as in
 
pointer x; 
 
???
 
pointer x would seem much simpler, yet given the way pointers are used, each pointer needs to know what type of data is stored at the
memory address that the pointer is holding.
 
So, if we say :
 
short *x;  x represents the name of a pointer that stores the address wherein at that address it is assumed that the value is of type short.
This allows us to denote how many memory blocks and of what storage type the memory address beginning with the first byte stored in x
 Actually is.
 
Examples:
 
short *x;  x refers (points to) a block of memory that is currently or will shortly store a short value, and that short value's 1st
 
           byte begins at the exact byte address stored in the pointer named x.
 
char  *x;  x refers (points to) a block of memory that is currently or will shortly store a char value, and that char value's 1st 
           byte begins at the exact byte address stored in the pointer named x.  
 
           Since a char value is only 1 byte, this address is all that is referenced by the x pointer if we indirectly request the 
           value at x.
 
           With short* x, 2 bytes would be indirectly referenced as a short requires 2 bytes, even though x will only store the
           memory address of the 1st byte.
 
double* x; x is now a variable that can store or hold an address that references (points to) a double value stored in memory with
           the double values 1st byte starting exactly at the address x contains.
 
Confusing possibly as I am not a textbook author, but it does get easier.
 
Code example at this point will help.
 
short  a = 5;    // short  variable a is holding the value 5
short* b = &a;   // short* variable b is holding the address where a is
                    in memory.
 
&a ? - the & operator here refers to the "address of operator".
 
&a is assigned to b.  &a is the memory address where a is actually in 
memory.
 
 
a  = 6; // store or assign the value 6 to the variable named a.
*b = 6; // store or assign the value 6 to the variable referenced by b.
           by referenced, we mean b points to a as b holds the memory
           address of a.
        // the * in *b is called indirection, and it is how we can access indirectly the value stored in the memory address b contains.
 
 
Flexibility:
 
A critical examples of flexibility is dynamic memory creation, where a single simple or structure data type variable or an array of a any
 variable  type can be created - ON DEMAND WHILE A PROGRAM IS EXCUTING - AND NOT PRE-DECIDED BEFORE THE PROGRAM STARTS TO EXECUTE.  A pre-defined array
 for example is known as a compile time array, the type of array's we have used in our first few exercises in 515.
 
Predefined short array named x of size 50
short x[50];
 
Dynamic memory allocation request for a short array of size 50, with the address of the start of that memory that the operating system finds 
available stored in x.
 
short* x = new short[50];
 
ONE CRITICAL TO KNOW CAUTION -> the short array in memory is NOT named.
One can not simply access this array by name, though it will appear that one can as detailed later as one can use statements after this
 Allocation such as:
 
x[0] =  5;
x[1] = 10;
x[2] = 15;
 
Actually, the block of memory here is being accessed via the x pointer, not directly by a specific name.  x is the name of a pointer.. and is a
separate variable .. so in memory we actually have:
 
1 - a short* variable (4 bytes) storing the address of the start of the
 memory block.
this short* variable is named x.
 
2 - also we have an UN-NAMED block of memory of size (sizeof(short)*50)
 bytes
that has NO NAME.
 
Therefore, the statement short* x = new short[50] creates a single
 short*
variable named x and a separate UN-NAMED block of memory for the array, and this block of memory can only be accessed via address variables
 (i.e.. via pointers - in this case, the variable x (a short*).
 
 
the new operator requests from the memory manager of the operating system a consecutive block of memory of size 50 shorts.  If the operating
 system can not find a block of consecutive memory this large that is free, the memory will not be allocated to the program, and NULL will be stored in
 x, designating that x holds the memory address of NOTHING - or no actual memory address.
 
How does x obtain the starting address of the block of memory?  
Answer:  the new operator returns the starting address and the =
 assigns
         this memory address value to x.
 
 
This seems like an un-necessary complication.  
 
If we simply needed a short array of size 50,  short x[50] seems to do
 just
as well as short* x = new short[50] - and actually it does.
 
The added flexibility can be seen with the following code...
 
int size;
cout << "What size of short array do you wish to have created ?";
cin  >> size;
 
short x[size];   // oops - this is illegal.  Only a constant (again
 pre-determined
                    size can be used such as 100, 50000, 100000.
 
Let's try this the more complicated way via a short* and the new
 operator.
 
 
int size;
cout << "What size of short array do you wish to have created ?";
cin  >> size;
 
short* x = new short[size];   // success - the exact size array of type
 short
                              // is allocated by the operating system
 and the
                              // starting byte of the array is stored
 in x.
 
Value of this flexibility?:
 
We can now request from the user the exact size of an array we desire, rather than setting the program up to use a very large size just in case the
 user might wish to have such a large size, and ooops - if the user actually needs more memory than the programmer or software designer thought would be
 necessary, they can request pretty much any size they wish as long as the operating system can find such a free unallocated (to another program) block of consecutive memory available.
 
Once again, if the memory management system of the operating system can not find such a memory block available, NULL will be the value the new operator
 will return to x.
 
Any additional flexibility possible with dynamic memory via pointers ? 
 
Yes, we can dynamically "delete" that memory or return that memory to
 the memory
manager for use by other programs at will.
 
delete [] x;   // de-allocate or delete the memory stored at x.  The [] tells the compiler that this is an array of data we are de-allocating.
 
Therefore, in summary, we can on the fly (as the program is executing), create and delete memory at will (actually request allocation and de-allocation).
 
 
Few operations that can be done with pointers.
 
1 - A memory value can be assigned to a pointer using for example the & or new operators.
 
2 - A pointer can be assigned the value of another pointer.  ONE CRITICAL caveat, both pointers must be referencing or be of the same type.
 
    short a;
 
    short* x = &a;
    short* y;
    y = x;           // legal as both y and x are pointers of type (or to) a short.
                     // both y and x now contain the same memory address, the
                     // address of the first byte where the short "a" is stored.
 
 
    short a;
 
    short* x = &b;
    long*  y;
    y = x;           // illegal - y and x are not of the same pointer type.
                     // x is of pointer type short
                     // y is of pointer type long
 
 
3 - A pointer can be incremented by an integer value.
4 - A pointer can be decremented by an integer value.
 
* 3 and 4 - the memory address simply is changed ( either up or down).
 
    short *x = &b;
    x++;              // x's stored value is increased
    x--;              // x's stored value is decreased
 
    Increased or decreased by 1 ?
 
    NO.
 
    The increase or decrease in value (memory address) is 1 * sizeof(type pointer) bytes.
    Example, char* x;  x++  -> x is increased by one byte as a char only requires one byte of memory.
    Example, short* x;  x++  -> x is increased by two byte as a short requires two bytes of memory.
 
5 - A difference can be calculated between 2 pointers.
 
    short a,b;
    
    short* x = &a;
    short* y = &b;
 
    short c;
    c = y-a;   // c will either be a + or - number representing the distance in 
               // memory x is from y.  Note, if a and b are consecutively next to
               // each other, c will not be 2 or -2 (difference in bytes between 
               // 2 shorts).
               // c will be 1 or -1
 
This comes in handy if we have an array of a data type.. such as shorts.
 
short *x = new short[size];
 
Since x stores the address of the 1st value in the array referenced pointed to) by x, *x will retrieve the 1st short value in the array.
 
cout << *x;   // output the 1st short value in the array
 
x++;          // proceed to the next short (change the memory address of x to the
              // next short value in the array (not the next byte).
 
cout << *x;   // output the 2nd short value in the array
 
 
Therefore, the code that follows here:
 
short i;
short x[100];
 
for(i=0;i<size;i++) {
    cout x[i]<<endl;
}
 
 
can be replaced by this code if we use pointers.
 
short i;
short size; // limiting the array size to the maximum integer
 able to be stored in a short.
 
cout << "Enter the size of short array desired ?";
 
short* x = new short[size];
 
 
for(i=0;i<size;i++) {
    cout << *x;   // output the value of the short stored at the memory address
                  // referenced by x.
 
    x++;          // change the memory address stored in x to the next short in 
                  // the array block.
}
 
 
Simple data type or structure pointers used as function parameters....
 
How does one go about passing a short* to a function.
Same as any other variable.
 
short* x = &b;
 
function(x);  // call the function named "function".
 
 
Function definition:
 
void function(short* x) {
   .... code ....
}
 
 
 
 
 
 
Array data type or structure pointers used as function parameters....
 
How does one go about passing a short* array to a function. 
Same as any other variable.
 
short* x = new short[size];
 
function(x);  // call the function named "function".
 
 
Function definition:
 
void function(short* x) {
   .... code ....
}
 
 
Did one notice they are the same ?   The short* named x is still a simply a short* in both cases (as a pointer to a short or a pointer
to a short array of size size.
 
 
Once inside the function - the short pointing to a single short can be used per example as follows:
 
*x = 10;
*x = 11;
 
x++;   // ooops - not smart but legal..  x now points to a memory
       // address that is 2 bytes past where x used to be pointing at.
       // how does one know that the 2 bytes past were x started is
       // actually being used as a short (or even if this memory is
       // allocated to the program at all ?
 
 
As an array... let's refresh...
 
void print_array(short* x) {
   for(i=0;i<size;i++) {
      cout << *x;
      x++;
   }
}
 
 
or to initialize all values of the array based on the rand() function:
 
 
void initialize(short* x) {
 
    for(i=0;i<size;i++) {
       *x = rand();   // store at the address referenced by x a rand()
 value.
       x++;
    }
}
 
Can an short* be passed by reference (&) ?  Yes, even if the pointer stores the starting address of an array, yet it cam be passed by
reference...
 
Example from a 520 assignment...
 
void init(short rows,short cols,short *&array2d, short *&arrayr, short *&arrayc);
 
array2d is a short pointer - in this case array2d is the start of a short[][].
arrayr and arrayc are also short pointers - but one can not tell if the arrays are one dimensional 
(short x[50] or two dimensional short x[50][100] – 50 rows and 100 columns or 50*100 short elements in size.
 
 
Note:  since array2d is simply a short*, it is passed as such. the *& in front of the array2d informs us that the function may alter the actual
starting address of array2d (a semi-advanced concept).  In this case, the array2d memory address is set in the init(ialization) function as
 follows.
 
void init(short rows,short cols,short *&array2d, short *&arrayr, short *&arrayc) {
 
        short size = rows*cols;
 
        array2d = new short[size];
        arrayr  = new short[rows+1];
        arrayc  = new short[cols];
 
        // initialize array2d
        int r;
        for(r=0;r<size;r++) {
            array2d[r]=r+1;   // each short element assigned a sequential value
                              // starting at 1.  Note that we can also use offset
                              // notation .. using array2d to represent the name
                              // or starting address of the array memory block.
        }
 
 
Another way to have done the same thing would have been:
 
        // initialize array2d
        int r;
        for(r=0;r<size;r++) {
            *array2d=r+1; 
            array2d++;
        }
 
 
NOTE:   The statement -> array2d = new short[size];
 
        The new operator returns the start of the allocated memory block to allow assignment to the short* array2d.
 
        Should we have not used the & in short *&array2d, the main() function that init() was called from would never know the address of
 array2d.
 
        main() called the init() function as follows:
 
             short *array2d; // 2 D array
             short *arrayr;
             short *arrayc;
             short rows,cols;
 
             cout<<"Input the number of rows: ";cin>>rows;
             cout<<"Input the number of cols: ";cin>>cols;
             cout<<endl;
 
             init(rows,cols,array2d,arrayr,arrayc)
 
Note, all the short*'s used for arrays when declared here in main are not actually referencing any memory.  Their values when so stated
is NULL, and when the new operator was used to assign a value to them, actually, they could have been assigned the starting memory of a single
short, a 1 dimensional array of shorts, 2 d array or shorts, 3 d array of shorts.. etc..   As long as the 1st value they pointed at via their
storing the address of a short was accomplished, all is legal.
 
 
Single dimensional arrays would work exactly the same, except there would be no need to multiply a number of rows * a number of columns to get a
 total  size for the array to be created. 
 
Ignore the complexity of 2 dimensional arrays until they are covered in the lectures - or read about them in a good textbook or online.  They are
 not actually that complicated, but the main purpose of this document is not to discuss 2,3,4 etc.. dimensional arrays.
 
 
This should be enough to get one started... along with a good text reference.... but, again DO NOT MISS CLASS LECTURES... as much more
 Flexibility and value will be discussed...  This document was simply created to be a primer or startup assistant to those unfamiliar with pointers - but
 truly, an textbook author who has had more time to carefully think out his/her writing .. their delineations of the purpose, flexibility, and
 operations one can do with arrays will certainly be more precise, accurate and easier to learn from.  If one has not learned pointers, find a book or
 professionally developed web site soon...
 
Please also get with a graduate assistant if one needs clarification on the issues or pointers or anything in this document.  Pointers for those
 not accustomed to them can be initially a bit of a challenge to get used to.. but they are a joy to a learned professional programmer, one such as
 you are now becoming if you did not have such skills prior to taking 515.
 
 
Pointers, a variable that holds a memory address.
Values, primarily flexibility and speed of execution.
 
 
Jim Major
Graduate Assistant
 
June 14, 2007