A main reason that pointers are used was mentioned above: to reduce the number of copies that need to be done to perform your functionality.
Take image processing for example. Say you have a function that takes an image data structure as an input and the goal is to invert the color. In a pass by value case, your function and call may look like
Code:
ImageType invert(ImageType input)
{
ImageType output;
/* do stuff to populate output with inverted input*/
return output;
}
ImageType img;
/* assume the image is populated at this point */
img = invert(img);
In this case, there are 3 copies of the image floating around. If the images are 5M a piece, that's 15M. Those large copies can really slow your system down; especially in a system with a small amount of resources.
If you take the pass by reference case, you would have something like
Code:
void invert(ImageType *img)
{
/* do stuff to invert img*/
}
ImageType img;
/* assume the image is populated at this point */
invert(&img);
Here, there is only one copy of the image. The passed argument is a pointer, and is most definitely smaller than the 5M image.
Pointers take some getting used to, but they can greatly improve your performance when passing large amounts of data around.
The only caveat is that it only improves things if your processor supports pointers well. In the recent IFI controllers, there was no native pointer support and pointer processing required many, many lines of assembly to accomplish. In that case, it was more efficient to pass the data around by value.
Another big reason for using pointers is to support multiple return values. Say you wanted had a function that took in an integer i , and returned both 2 * i and 3 * i. You can't really do this directly with pass by value (you could if you returned it in a struct), but with pass by reference, you can do the following
Code:
void func(int i, int *j, int *k)
{
*j = 2 * i;
*k = 3 * i;
}
int x, y;
func(3, &x, &y);
I hope this helps to things for you.