let me see if I can give you a CLEAR reason why pointers are so useful...
I'm gonna assume you understand the basic concepts of computer memory. I'll further assume you understand about virtual memory so I don't have to make my answer complicated. fair enough?
Old-school programming (PL/1, COBOL, even BASIC) contains a concept of "working-memory". That is the memory currently loaded and in use for an executing function. In todays programming languages (like C,C++,JAVA, C#, etc) you would refer to "working-memory" as local variables (that are allocated from the "stack" and discarded after the function concludes execution).
In the U.S., a telephone is 10 digits (310-555-1234). You have the telephone numbers of 1,000 people. You want to be able to look through your list of phone numbers. You have "working-memory" for the telephone number you are currently looking at.
Each time you want to look at the next (or previous) telephone number in your list, you have to copy the telephone number into your "working-storage". The (object) code required to copy memory (from your telephone list to your working-storage) is significant (not TOO much but alot if you consider you have to redundantly call it a ca-jillion times).
An alternative to executing all that unnecessary memory copying code is to just "move the address at which you're look at". So instead of "copying" the memory, you're just changing "where" you're looking.
Let me explain in code:
typedef struct _tagTelephone
{
int NPA; // area code
int NXX; // first 3 digits
int LATA; // last 4 digits
} TELEPHONE;
TELEPHONE myTelephoneList[1000];
int lookThruNumbers(int theNumberIwantToLookAt); // between 0 - 999
// WITHOUT POINTERS
int lookThruNumbers(int theNumberIwantToLookAt)
{
TELEPHONE thisTelephone;
memcpy(&thisTelephone, &myTelephoneList[theNumberIwantToLookAt], sizeof(TELEPHONE));
printf ("NPA = %d\nNXX = %d\nLATA = %d\n", thisTelephone.NPA,thisTelephone.NXX,thisTelephone.LATA);
return 0;
}
// WITH POINTERS
int lookThruNumbers(int theNumberIwantToLookAt)
{
TELEPHONE *pthisTelephone = &myTelephoneList[theNumberIwantToLookAt];
printf ("NPA = %d\nNXX = %d\nLATA = %d\n", pthisTelephone->NPA,pthisTelephone->NXX,pthisTelephone->LATA);
return 0;
}
NOW.... Both functions will work properly. However the function using pointers doesn't have to copy any memory in oder to look at your list. We're just changing WHERE we're pointing at. Thusly, the function using pointers will execute MUCH faster than the one not (using pointers).
A SIDE-NOTE for you to consider...
Did you see the variable "TELEPHONE myTelephoneList[1000];"? THIS IS A POINTER! "myTelephoneList" points to a block of memory that is 12K (3 ints * the size of an int -- 4 bytes * 1,000 telephone numbers.. or 12K). So its my guess that if you've been working with C/C++, you've been using pointers for a while (without even knowing it).
Today's languages that utilize "references" have matured the reference mechanism so you don't have to think indirectly about pointers (or the mechanics for managing them). The underlying implementation for a reference is STILL a pointer -- its just managed for you.
So with managed pointers (or references) why do you still want to care about pointers? Here's your answer...
Always use the right tool for the right job! If you're writing a game, an operating system, a database platform, or some OTHER testicle-smashing project, you really want to make sure not ONLY your implementation is optimized but your design as well. Minimizing your executable foot-print, the amount and usage of your memory, the speed of your I/O are all factors that you may elect to remove your training wheels of having modern-day compilers "give" you code for your own protection. Removing said code will give you MANY oportunities to realize such optimizations. If you're writing a "Hello World!" app, then you can forget about pointers and let the compiler keep you fat, dumb & happy!
Hopefully this was easy enough to understand.