Pointers, from a beginners standpoint, can be an intimidating feature of c++. However they are also very useful which makes them an important feature to learn.

NOTE: For this entire tutorial, operators will be labled green, keywords labled blue, and variables will be labled red for clarity. Also, a .txt version of the tutoiral is available at the bottom of this post.

Before we analyze any pieces of code, it is important to realize that a pointer does not contain a value as a variable, such as an int or char would. It cannot be emphasized enough that pointers must be viewed as just that, pointers. They simply point to a location in memory which can be modified directly using that pointer.

Let's use an analogy to drive this point: you have two jars, with a piece of paper in each. On one of the pieces of paper you write the number 7, and place it in the jar. You then take this jar and place it somewhere in your home. Now on the second piece of paper, you write the location of the first jar and place it in the second jar. This second jar acts as a pointer to the location of the first jar which contains the number seven.

Syntax
First lets look at the syntax of a basic pointer; this one is of type char:

char* myfirstpointer;

Really the only difference from declaring a variable is the * operator. This operator tells the compiler to create a pointer of type char. In this example the * trailed the datatype (char) however another option to syntax is to place the * before the variable name.

char var,*ptr;

Again, first you state the datatype, then the name of the variable, in this case only ptr would be a pointer, var is still a character because it has no leading *.

So what exactly does this pointer POINT too? Nothing. We have simply created a pointer, ready for pointing, ha! So lets make this pointer POINT to something in our memory.

Value vs. Address - Referencing and De-Referencing

int main()
{
int x = 7;
int* pointer = &x;
}

First we make a basic variable of type int and assign the value 7 to it. This 7 is now located somewhere in our memory. Again we declare a pointer as described above, this time of type int. This time though we not only declare the pointer but we make it point to something at the same time; just as you can declare a variable and give it a value at the same time. The & operator may look new to some of you. The & operator references the variable x. In other words it gives the address in memory of x. This is important because we only want the ADDRESS of the variable x, not the actual value.

The best way to see the & operator at work is to output the variable, and the same variable referenced:

On the first line you should see the value of x, 1337. On the second line you will see the address of x in memory, which probably looks like 021FF7C. Now that you have seen the & operator at work lets tie this back in with pointers.

Here we assign variable x to the value of 1337, and assign pointer to the address of x. Finally, you can see that, indeed, pointers only contain addresses. The first line of output should be the assigned address, in this case, the address of x. Just to prove this, the second line outputs the actual address of x. The first two lines should read the same.

Now the third output is the VALUE at the address stored to the pointer. This, of course, is 1337. But I thought pointers only contain addresses and not values. Indeed they do, but this address points to a value in memory. This value can be viewed by DE-referencing the pointers stored address. Just as we can reference values stored to addresses by using the & operator, we can also DE-reference the addresses to values. This de-referencing is done by the * operator. The * operator in front of pointer states that we want to see the value stored to the address pointer holds.

Modifying variables using pointers
The value of x can also be modified by using pointer:

x is assigned to 1337, we then assign the address of x to pointer. The first output is used to show that the value of x is 1337, but then we change the value of x by using ptr.

*ptr = 54;

The value of the address stored to ptr = 54

Again, it is very important to remember that ptr does not contain the value of x, only the address, and that by de-referencing the address we can set the value of x through ptr. This could be said as a sentence to better understand it.

The value at(*) this address(ptr) = 54;

Finally the second output will display that 54 is now the value of x.

Arithmetic operators and pointers - Accessing arrays with pointers
Arithmetic operators can be used on pointers to change the address the pointer points to. This can best be shown by making the pointer point to an array, this time of characters.

char str[11] = Dark_Nexus;
char* ptr = str;

Because str is an array, just using the variable name supplies the address to the array so there is no need to reference it with &. The following line would achieve the same goal.

char* ptr = &str[0];

Because str[0] actually contains a value we have to reference it with &. Now ptr, either way, points to the head of the array str. Just as you can move through an array with the [] brackets, you can also move through a pointer in the same way. 0 indicates the head of the array, and in this case 10 would be the end of it.

cout << ptr[0] << endl;
cout << ptr[10] << endl;

These two outputs would display the first and last character of the character array str, because ptr points to the memory used by str. You may be asking why don't you have to dereference ptr[0] or ptr[10]? They are values not addresses. In this case you do not have to de-reference the address as the brackets [] do it for you. The values of the character array can also be modified in this manner.

ptr[0] = ptr[10];

Because we already know 0 is the head of the array, and 10 is the end we can assign position 0 to position 10 in the string. No de-referencing is required as, again, the brackets[] do it for you. If you were to output str now, it would read "sark_Nexus"

Now that we have seen how to use a pointer with an array, we can actually talk about arithmetic operators and pointers now.

cout << ptr + 1 << endl;

;

ptr still points to str, and in this case str has returned to "Dark_Nexus". ptr + 1 indicates a shift (in this case an increment) from the address ptr is pointing to. When arrays are declared, all the memory is allocated at the same time, so each array element will be right next to the other, running from 0 to 10 for this string. ptr only contains the address to the head of the array, so by using ptr + 1, moves to the next address (ptr + 2 would mean move two addresses forward). The output would be ark_Nexus. However ptr still points to the head of the array because we have just added 1 to the address of ptr only for the duration of the statement. Once the statement is over ptr will still point to the head of the array. Now let's say we only want ptr to point to the Nexus portion of the string. This can be achieved by using the += operator.

ptr += 5;

To better understand this operation you could think of the statement as ptr = ptr + 5. "Dark_" is 5 characters long, so we simply have to move 5 characters (or addresses) forward. ptr now points to array slot 5, or N. If you were to output ptr now, it would read Nexus. You guessed it, you can use lots of other arithmetic operators too, here's a list summarizing their effects:

These are the basic ways to modify the location in memory a pointer points to, all other arithmetic operators apply. If you were using more than one pointer to point to the same piece of memory, modifying the address one pointer points too will not affect the other pointer's address. However, if the value of the memory was modified, the pointers would reflect that change.

You guessed it again, you can make pointers to objects too!! (along with any sort of datatype). Again, I must stress that a pointer to an object STILL simply points to the address where the object is held in memory. When accessing a member of an object you simply use -> instead of .

We make a structure called mystruct and then make an object of type mystruct. Finally we make a pointer to the object of type mystruct and assign ptr to the address of myobject using the & operator.

mystruct* ptr = &myobject;

var1 is set to 7 and var2 is set to 493 by using ptr, however you may have noticed that I never de-refrenced ptr. That's because the -> de-references it for us, just as the []'s do for arrays. Lastly, var1 and var2 are outputted by using both the object and the pointer to prove that we have indeed modified the variable.

You would access a class' members the same way as it is an object also.

Managing heap memory - new and delete keywords
In the previous example, the memory our pointers pointed to were part of the stack. This stack is allocated pre-compile, and is also deleted after the program run.

The difference between the stack and the heap is that the stack is allocated before the program executes, where the heap contains memory allocated DURING the program run.

The new keyword is used to allocate memory during the program run. Syntax looks like this:

new char;

new signals to allocate new memory in the heap, char indicates what kind and how much. In this case we have made room for a single character. You could just as easily make room for 20 integers.

new int[20];

Again, new signals to allocate memory in the heap, int indicates of what kind, and [20] defines how much. Remember that all the memory for arrays is allocated at the same time, so they will be placed together in memory. You definitely do not want to just create memory in the heap without being able to manage it though, so how do you manage your newly allocated memory? After the program ends, unlike the stack, the memory in the heap remains, this leads to memory leaks and other nasty things. So never allocate memory in the heap without having a pointer point to it. This can be done when you declare the pointer or later in the program when you wanted to assign another pointer to the same memory, the following illustrates both methods:

int* ptr1 = new int[10];

Declare ptr1, allocate memory in the heap, make ptr1 point to the newly allocated memory.

int* ptr2;
ptr2 = ptr1;

Assuming ptr1 still points to the memory allocated in the previous example, you can now assign ptr2 to ptr1, however they are independent of each other, they just both point to the same memory.

I said before that memory placed in the heap is not automatically deleted when the program ends so you have to manually delete memory using the delete keyword.

delete []ptr2;

The delete keyword deletes all memory tied to the pointer. The [] means that you want to delete all of the memory not just the first address (or whatever address) ptr2 is pointing too. If ptr2 did not point to an array, and just a single int, you would not have to use the []'s.

int myint = new int;
delete myint; //No brackets for a single peice of data

We don't have to delete pt1 because they both point to the same memory, however when your pointers are idle or don't point to anything, it is a good idea to set them to NULL so that they don't point to random addresses in memory.

ptr1 = NULL;
ptr2 = NULL;

memcpy(...) - Application of pointers

Whew, now that we have gotten past the enigma of pointers, let's take a look at an application of them. At the same time we will introduce the memcpy() function

The following function searches through a string for a sequence of characters, once it is found, the position of that sequence in the string is returned as an integer, or -1 if the characters were not found.

Let's say the string we are looking for the character sequence in is "Dark_Nexus" and we are looking for "ex".

In this function, the keyword const appears in the parameters. This means I won't be able to change the memory that the pointers point too as we are taking them as a constants. This is just safe programming because this function only needs to look, not touch.

char*str is the string which we want to look throughchar*control is the string we are looking for within str, or the control

Next, intpos is set to 0. pos will keep track of where we are at in the string, the head of the string being 0. intlen is used to store the length of control, we will need to know how many characters are in the control so that we only compare that many characters at once.

The next line allocates memory in the heap of type char. It will make room for len + 1 characters, or the length of our control string + 1. The + 1 is there so we can append a null-terminating character to the end of the string: \0.

Before we look at what the do loop does, let's have a look at that while statement. Remember you can access the value of a pointer with []'s, which is what we do here. str[(len+ (++pos)) - 1] . if len = 2 (because control was "ex") and pos starts at 0, it will make sure there is a value (not \0) at str[1] for the first loop. This looks ahead to make sure we don't start checking the wrong memory.

In the loop, the first line uses memcpy(...). memcpy(), or memory copy, takes 3 parameters: destination, source, and how many characters to copy.

memcpy(buffer,str + pos,len);

The destination is buffer, and the source is str + pos, for the first loop pos is 0 the source for the copy will start at str + 0, or the head of the string (for the next loop iteration pos would be 1, so the source for the copy of that iteration would start at str + 1, or "arK_Nexus"). Finally, the count parameter is set to len, in this case len is 2 so it will only copy 2 characters fromstr + pos to buffer.

Example:

-First iteration of the looppos = 0;str + pos = Dark_Nexus;
After memcpy() the memory pointed to by buffer would be "Da"

-Second iteration of the looppos = 1 (because of ++p at the end)str + pos = arK_Nexus
After the memcpy() the memory pointed to by buffer would be "ar"

The next line of code appends a null-terminating character to buffer at position len. In this example len is 2: buffer[2] = '\0'. Remember that when we allocated memory for buffer, it was len + 1, or 3

The next line simply compares buffer against control, if they are the same, then we delete the memory tied to buffer, because we no longer need to use it.

delete []buffer;

And finally return pos, or the position of control in str, starting at 0.

Dark_Nexus
0123456789

So control (ex) is found at position 6, which is what the function returns.

This post has been edited by JackOfAllTrades: 06 July 2011 - 05:22 PM
Reason for edit:: Changed void main() to standard int main()

Thanks Dark_Nexus for the great tutorial on Pointers, it helped a lot with my class this week. The way our textbook explained pointers left me with a lot of questions. This tutorial helped to answered almost all of them.