Pointers

So far we’ve seen many different types in C.
The int, holds an integer value.
The char, holds a character.
The float, holds a decimal place value, etc.

Recall that as explained in an earlier page, all these variables, when declared reside in the system memory. They are each assigned an address and reside at that exact address.
The following declarations:

int q = 17;

memory_table2
As you can see, q is assigned to the address 0x2.

This leads us to the question, how can we indirectly change the value of q, to 3. That is, without directly writing the code q=3.
This is where pointers come in.
A pointer is another “type”.
An int holds an integer, a pointer holds an ADDRESS.
We can have different kinds of pointers, a pointer to an integer, is not the same as a pointer to a character or a float.
To declare a pointer we write the following:

int* p;

The * after the keyword int, means that p is declared as pointer to an integer.
We can assign it a value like so.

int q = 12; //here we declare an integer and assign it an integer value of 12

int* p = &q; // here we declare a pointer to an integer an assign it the ADDRESS of q 
//alternatively
int* p;
p = &q; //this is the same as above, just doing it in separate lines

Dereferencing Pointer
When changing the value of an integer, q we simply say q = 2.
When working with pointers it is very important to differentiate when we wish to change the pointers value, ie. CHANGE THE ADRESS THE POINTER HOLDS, vs. modifying the variable that the pointer is pointing to.

int a = 4; //declare integer, called a, assign it 4

int* P; //declare a pointer to integer, still uninitialized

p = &a; //assign the address of a to p. p is now pointing at a

Now say we want to change the value of a, we need to do “dereference” p. That means say: “where is P pointing to? Go there find the variable its pointing at and get that value”.

int a =4;
int* P;
P = &a;

*P = 3;

The above line is dereferencing P. By putting the star in front of a pointer name we are saying that we want to work with the actual value it’s pointing to.
*P = 3 is IDENTICAL to writing
a = 3;

Note:
what if we wrote:
P = 3 ?
This is an ERROR. If you just write P on its own, you are working with a pointer, anything you assign to it, it will be interpreted as P is now pointing to the address 3. This is nonsense since you don’t actually know what exists in that address in memory.
To change the value of the pointer you assign it a different address using the ampersand symbol, OR you can equate it to another pointer.
As seen below:

int a =4;
int* P;
P = &a;

*P = 3;


//assigning pointers to other pointers
int* x;
x = P; // makes X point to whatever P is pointing to, in this case a.
*X = 2; //since X is pointing to a, this line is EQUIVILIENT to writing:  a = 2

As you can see, variables of type int pointer can be assigned to one another. Since P was pointing to a, we declared X as a new integer pointer and said: X=P; X now holds the address of a.

Working with Pointers
Once you declare a pointer and initialize it to point to an existing variable, you can dereference the pointer and use it as you would a regular variable of that type.
Let’s take a look at a previous program we wrote using integers:
From the section on iteration we wrote a program that will ask a user for input, then print out all the digits of the input.
Here is the code:

int userIn;
int LastDig;

scanf("%d", &userIn);

while(userIn)
{
   LastDig = userIn % 10;
   printf(" %d ", LastDig);
   userIn/=10; 
}

Now let’s redo this except declare a pointer to integer, have it point to the variable userIn, than leave userIn alone for the remainder of the program and just work with the dereferenced pointer.

int userIn;
int LastDig;

int* P = &userIn; // declares an integer pointer, P, assigns it to point to UserIn


scanf("%d", &(*P)); //Explained below

while(*P)
{
   LastDig = *P % 10;
   printf(" %d ", LastDig);
   *P/=10; 
}

Note the scanf line: scanf(“%d”, &(*P));
As we said before, when we dereference P, writing *P it’s just like any integer variable. So to use scanf on it, we say the address of *P.
HOWEVER, since P is a pointer, which contains an address, we don’t need to dereference it, and than say go to the address, we can just say P!!
Hence the line: scanf(“%d”, &(*P));
is equivalent to:
scanf(“%d”, P);

Pointers to Pointers
We’ve now seen that we can have a pointer that points to an integer. But, what about a pointer that points to an int-pointer? How about a pointer that points to a pointer to an int pointer?
These are all completely valid.
Here was what it would look like:

int myInt = 4;

int* pI = &myInt;
int** ppI = &pI;
int*** pppI = &ppI;
int**** ppppI = &pppI;

****ppppI = 2;
//myInt is now 2

To the joy of any first year programming professor, the above code is very confusing. These are very commonly seen as test questions where multiple pointers to each other are initialized to different values and then changed many times around. The output must be determined.
If you decompose these pointers, you see that
int* pI is a pointer to an integer.
int** ppI is a pointer to a pointer to integer.
int*** pppI is a pointer to a pointer to a pointer to integer.
And so on.
Dereferencing them is the same way…
With pointer to intger:
int* pI;
If we use pI, that is a pointer, we assign it an address to an int.
However if we dereference it by writing *pI, that is an integer and we assign it integer values.
Similarly,
ppI is a pointer to a pointer to integer, hence we can assign it the address of a pointer to integer.
*ppI becomes a pointer to an integer, ie. we assign it the address of an integer
whereas **ppI is the integer itself, and can be assigned an integer value.
The following diagram should make it easier to visualize what is actually happening in memory.

pointertopointertopointer

As you can see, the only integer type variable is located in the address: 0x2 and has the identifier: myInt, it holds a value of 3.
Down in the address 0x4 we have a pointer to an integer, pI. It’s value is the address of myInt, 0x2.
Moving on, at 0x6 we have our pointer to a pointer to integer, ppI. As you can see, this holds the address of pI, the integer pointer, 0x4.

Example Problem
Here is an example from the 2014 Midterm Exam for APS105 – Computer Fundamentals, a first year programming course in C, at the University of Toronto, faculty of Applied Science & Engineering.

int first = 1, second = 10;
int *pointerToFirst, *pointerToSecond;

pointerToFirst = &first;
pointerToSecond = &second;

*pointerToFirst = *pointerToSecond - *pointerToFirst;
*pointerToSecond = *pointerToSecond - *pointerToFirst;
*pointerToFirst = *pointerToSecond + *pointerToFirst;

printf("%d, %dn", first, second);

Following the declarations we see initially we have 2 integers:

int first = 1, second = 10;

We then declare 2 pointers to integer, and assign each of them to the integers.

int *pointerToFirst, *pointerToSecond;

pointerToFirst = &first;
pointerToSecond = &second;

So, we have a pointer called
pointerToFirst pointing to and integer called first.
and a pointer called pointerToSecond pointing to an integer called second.

Now let’s see how they change.

*pointerToFirst = *pointerToSecond - *pointerToFirst;

This line dereferences the pointer called pointertoFirst, and assigns it a different value. Hence, whatever it was pointing to, in this case First also changes.
*pointertoSecond is the value of second, 10. and *pointertoFirst is the value of First which is 1. Their difference is 9.
Hence the value of First has been changed to 9.

Moving onto the next line:

*pointerToSecond = *pointerToSecond - *pointerToFirst;

Now we change the value of Second since we are dereferencing pointertoSecond and assigning it a new value.
*pointerToSecond has the value of Second, which is 10, and *pointertoFirst is the NEW value of First, since in the pervious line we had reassigned it to 9.
So the difference of 10 – 9 is 1.
The new value of Second is 1.

Let’s look at the last line:

*pointerToFirst = *pointerToSecond + *pointerToFirst;

Here we again dereference pointertoFirst and change its value. Hence changing the value of First again.
We dereference pointerToSecond, obtaining the value of Second which was changed in the pervious line, 1.
*pointerToFirst gives us the value of First, which is 9. Summing these 2 values together results in First now being 10.

So to recap,
we first changed first from 1 to 9
Then we changed second from 10 to 1
then we changed first from 9 to 10

The last line is just printing them off:
Output is 10,1

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s