next up previous contents
Next: Arrays and Pointers in Up: Pointers and Malloc Previous: Pointers and Malloc

Memory and Pointers

To be blunt, most of this section should be a review. If much of the material in this section is completely new to you, then there is a good chance that you are not prepared to take S-Q. The majority of the things we'll do in this course require extensive use of pointers, and this material must be understood in order for you to complete the assignments.

Memory and Addresses

C treats memory as a large array of bytes. Every piece of memory that a program uses actually resides somewhere in this array.

The address of a location of memory is the index of its beginning in this ``memory array''. It is often useful to refer to a variable or other object by this location, instead of by its name. In fact, this is the only possible way to deal with dynamically allocated objects (discussed in section B.3.1), which do not have names in the usual sense.

A pointer is a C term for an address; pointers and addresses are synonymous, even though one or the other is usually used in particular idioms. (This may seem confusing at first, but after a while you won't even hear the difference.)

C Syntax for Pointers

C has two operators for working with pointers.

&

Take the address of or get a pointer to some location in memory.

*

Deference an address or follow the pointer. Fetch the value stored at the given address.

These are both unary operators (i.e. they have one operand), and they come before the expression that they operate upon.

In C, pointers have specific types. The type of a pointer is that of a pointer to the type of thing that it can point to. This type is specified by following the type pointed to with an asterix (*).

    int i;            /* i is an ordinary int.       */
    int *ip;          /* ip is of type "int *".  It  */
                      /* is a pointer to an int.     */
    int **ipp;        /* ipp is of type "int **"; it */
                      /* is a pointer to a pointer   */
                      /* to an int.                  */

Be careful, however, because the asterix in one of these types is associated with the variable, not the type. For example:

    int i;            /* i is an ordinary int.       */
    int *ip1, ip2;    /* ip1 is of type "int *", but */
                      /* ip2 is an ordinary int.     */

For this reason, most C programmers place the asterix in a pointer type at the start of the variable name, rather than the end of the type, in order to avoid confusion. Instead of writing ``int* ip'', which makes it look like the int and the asterix are somehow bound together, they would write ``int *ip''.

The exception to the strict typing of pointers is the void pointer type, which can point to something of any type.

Pointer casts can be used to override these types (in a manner similar to the way that type casts can be used to convert integers into doubles and vice versa). Pointer casts are generally something to avoid, except in the case of a void pointer. A void pointer must be cast (or assigned to a variable of a specific variable type) before it can be dereferenced.

As an example of the use of pointers, consider the code shown in figure B.1. After this code is executed, the result is illustrated by figure B.2.

 
Figure B.1:   A simple pointer example.

 
Figure B.2:   The result of the simple pointer example.

With these pointers set up, there are now several ways that we can access the value stored in the variable foo. We can use foo itself, as always; the fact that other variables point to foo does not limit the way that we use foo in any manner.

        foo = 12;       /* assigns the value 12 to foo. */

        printf ("%d\n", foo); /* prints the value of foo*/

We can also access the value stored in foo via the pointer from bar to foo:

        *bar = 12;      /* assigns the value 12 to      */
                        /* whatever bar points to.      */
        printf ("%d\n", *bar); /* prints the value of   */
                        /* whatever bar points to.      */

Since qux points to bar, and bar points to foo, we also can deref qux twice in order to access foo:

        **qux = 12;     /* assigns the value 12 to      */
                        /* whatever the pointer qux     */
                        /* points to points to.         */
        printf ("%d\n", **qux); /* prints the value of  */
                        /* whatever the pointer qux     */
                        /* points to points to.         */

Call by Reference versus Call by Value

In general, C functions use call by value for passing their arguments: the value of expressions used as arguments to functions are passed to the functions, and not the expressions themselves.

For example:

void foo (int y)
{
    y = 5;
    printf ("y inside foo = %d\n", y);
    return ;
}

int main ()
{
    int x = 10;

    printf ("x inside main = %d\n", x);
    foo (x);
    printf ("x inside main = %d\n", x);
    return ;
}

In this example, when main calls foo, the value of x, which is 10, is passed to foo, and winds up in foo's own copy of y. If foo changes the value of its y, the value of x inside main is unchanged.

When this program is run, it will produce the output:

x inside main = 10
y inside foo = 5
x inside main = 10

However, pointers allow you to sidestep call by value. Instead of passing a copy of the value to the function, you can pass a reference (or pointer) to the variable to the function. The function can then dereference the pointer, and change the variable as it pleases. This way of passing parameters is called call by reference. For example:

void foo (int *y)
{
    *y = 5;
    printf ("*y inside foo = %d\n", *y);
    return ;
}

int main ()
{
    int x = 10;

    printf ("x inside main = %d\n", x);
    foo (&x);
    printf ("x inside main = %d\n", x);
    return ;
}

This program will produce the following output:

x inside main = 10
*y inside foo = 5
x inside main = 5


next up previous contents
Next: Arrays and Pointers in Up: Pointers and Malloc Previous: Pointers and Malloc

Dan Ellard
Mon Jul 21 22:30:59 EDT 1997