Guides:C/C Crash Course/Pointers

From CoderGuide

Jump to: navigation, search

Back to TOC

A word of warning: This section will be confusing, and it takes programmers a long time to get the hang of pointers. You'll see why they are important later, and are required for dynamic memory allocation and dynamic arrays. So, it's perfectly normal if you can't figure out what all this pointer stuff is about in the beginning, but keep it in mind as we will be using them more later.

Pointers

Pointers are a special kind of variable. Basically they store the location in memory, or reference, to where some data is stored. They have special uses, but, if care is not taken, they can introduce some very nasty bugs in a program that can be hard to trace. A pointer is defined just like any other variable, except the name of the variable is prefixed by a asterisk '*' to indicate that the variable is actually a pointer to some data of that type. A normal variable can be converted into a pointer by prefixing it's name with a ampersand '&' during assignment of function calls. To convert a pointer to a normal variable, you prefix it with a asterisk '*' during assignment (asterisks are also called "stars", but "asterisk" is the formal name for the character). Confusing? You bet, and it does take some time to get the hang of it-- it's also one of the most common reasons why programs fail: failure to keep track of those pointers. But here is an example to try and explain things a little better:

#include <stdio.h>
 
int main(){
        int *ip1,*ip2; /*two pointer, but we can't safely use 
                         them yet.*/
        int i1,i2,i3; /*a few normal variables*/
 
        i1=10; /*assign some values to our three integers*/
        i2=11;
        i3=12;
 
        ip1=&i1; /*Assign the reference to the integer i1 to the 
                       pointer ip1.*/
        ip2=ip1; /*assign the value of ip1 to ip2 (which is only a 
                   reference)*/
 
        /*The %d tells printf to display an integer.  The stars before 
          the two pointers tells the compiler to return the value of 
          the data stored at the reference which is stored in the
          pointer.*/
 
        printf("ip1:%d ip2:%d\n",*ip1,*ip2);
 
        i1=100; /*assign 100 to i1*/
 
        printf("ip1:%d ip2:%d\n",*ip1,*ip2);
 
}

The output will look like:

ip1:10 ip2:10
ip1:100 ip2:100


The reason why the numbers displayed are different even though the ip1 and ip2 weren't changed after the first call to printf is that we changed the value of the data both ip1 and ip2 were pointing to, which was the data in i1. Whenever you use the name of an array without the brackets to reference a single element, you are using that array just as you would any other pointer.

You can also have a pointer to a pointer. That is a pointer that points to another pointer, that points to some data in memory. To define one of those you use two stars rather than just one. One of the places these are used are for arrays of strings (or an array of arrays). The main function, the first function that is called when your program runs, uses one such pointer to a pointer for holding the parameters that were passed to it when executed.

Pointer Arithmetic

There's another very interesting thing that we can do with pointers: We can add and subtract integers to them (and perform any other mathematical operation with integers). When we do this, we're telling the reference to point to some other location in memory. Now, special care must be taken to ensure that you only access memory that your program has allocated for it's use, otherwise some nasty things can happen, such as your computer crashing or the operating system killing your program abruptly.

The only time you can safely use pointer arithmetic is when your pointer is pointing to an array, such as a string. With strings (a character array, not to be confused by the string class in C++ or Java), we can pretty much assume that, on all computer systems, each element is exactly one byte in length, so we can just add or subtract one to access the next or previous element of that array. We can make no such assumption with any other data type in C. What you can do, is get the size of a data type by the sizeof operator. To use the sizeof operator, you just type something like "sizeof int" and then the compiler will replace that statement with the number of bytes that data type uses (in this case, an integer).

Here is an example:

char s[10],a; /*a character array, and a character variable*/
 
a=*s; /*assign a the first element of s*/
a=*(s+1); /*assign a the second element of s*/
a=*s(s+2*3);/*assign a the seventh element of s*/
s=s+1; /*Make s now start referring to the second element of the
         initial array (now we're only using the last 9 of the
         original 10 elements-- but they're all still allocated
         in memory).
*(s*666)=a; /*Ummm... cause your program to crash really bad :-) */
Personal tools