Understanding pointers

The basics of pointers and references are pretty simple. A pointer is nothing more than a variable that can hold the address of another variable. A pointer declaration is exactly like a variable declaration, except you put a '*' between the type and the variable name:

int x;  // declares an int variable named x
int *px // declares a pointer variable, which points to an int variable

You initialize a pointer by giving the name of the variable you wish it to point to, preceded by a '&':

px = &x;  // initialize px to point to x

You use a pointer just like you use a variable, except you precede the pointer name with a '*':

x = 3;  // put the value 3 into variable x;
*px = 5  // put the value 5 into variable x, using px

Those are the basics.

A reference is actually syntactic "candy" for a pointer. References are a "safer" way to use pointers. If you use a pointer to write a variable, and the pointer is not properly initialized to point to that variable, the write will clobber something, somewhere, in memory. So, pointers must be used with great care. A reference allows you to do the same things you would do with pointers, but the compiler can do a much better job of making sure you use it correctly.

One of the most common uses for a reference is to allow a function to return more then one value. Normally, a function can only return a single value, of a single type, using the "return" statement. In c, one gets around this by passing a pointer as a argument to a function, and the function can then modify a second (or third, or fourth) variable by accessing it through the pointer argument(s). References allow you to do that, but with "nicer" syntax. The argument list for the function specifies the argument is a reference, again, by following the argument type with a '&'. Other than that, the function treats the argument like any other, except when the function accesses the reference variable, it is accessing the actual variable itself, rather than a temporary copy of the variable that exists on the stack, and is discarded as soon as the function returns.

int dodiv(int x, int y) // declare a function that takes two int argument, and returns an int
{
    return x / y;  // return x divided by y
}

Take the above simple function. What happens it y == 0? The divide returns an incorrect value. Wouldn't it be nice if the function could return a second return value that indicates y was zero? Well, it can:

boolean dodiv(int x, int y, int &result) // declare a function that takes two int argument, and returns an int
{
    boolean ret = true;

    if (y == 0)  
    {
        // uh-oh, y is zero, so flag an error
       ret = false;
    } else
    {
        return = x / y;  // return x divided by y
    }
    return ret;
}

Now, if y == 0, the function returns true, indicating an error. Otherwise, it returns false, and the result of the division is put directly into the reference variable the caller provided. This function would be called like this:

int myx, myy, my result;
...

if (dodiv(myx, myy, myresult))
{
    // divide was successful, and result is in myresult
} else 
{
    // divide failed, because y == 0
}

Bottom line, pointer should be avoided, especially for newbies, as they are dangerous if not used properly. Reference variables are a better way to go in most cases. Neither should be used except when really necessary.

Regards,
Ray L.

2 Likes