Pointers: A First Look

I l @ ve RuBoard

Pointers: A First Look

Pointers? What are they? Basically, a pointer is a variable (or, more generally , a data object) whose value is an address. Just as a char variable has a character as a value and an int variable has an integer as a value, the pointer variable has an address as a value. If you give a particular pointer variable the name ptr , then you can have statements like the following:

 ptr = &pooh;  /* assigns pooh's address to ptr */ 

We say that ptr "points to" pooh . The difference between ptr and &pooh is that ptr is a variable, and &pooh is a constant. If you want, you can make ptr point elsewhere:

 ptr = &bah;  /* make ptr point to bah instead of to pooh */ 

Now the value of ptr is the address of bah .

To create a pointer variable, you need to be able to declare its type. Suppose you want to declare ptr so that it can hold the address of an int . To make this declaration, you need to use a new operator. Let's examine that operator now.

The Indirection Operator: *

Suppose you know that ptr points to bah , as shown here:

 ptr = &bah; 

Then you can use the indirection operator * (also called the dereferencing operator) to find the value stored in bah . (Don't confuse this unary indirection operator with the binary * operator of multiplication.)

 val = *ptr;  /* finding the value ptr points to */ 

The statements ptr = &bah; and val = *ptr; taken together amount to the following statement:

 val = bah; 

Using the address and indirection operators is a rather indirect way of accomplishing this result, hence the name "indirection operator."

Summary: Pointer-Related Operators

The Address Operator:

General Comments:

When followed by a variable name, & gives the address of that variable.

Example:

&nurse is the address of the variable nurse .

The Indirection Operator:

*

General Comments:

When followed by a pointer name or an address, * gives the value stored at the pointed-to address.

Example:

 nurse = 22; ptr = &nurse;  /* pointer to nurse */ val = *ptr; 

The net effect is to assign the value 22 to val .

Declaring Pointers

You already know how to declare int variables and other fundamental types. How do you declare a pointer variable? You might guess that the form is like this:

 pointer ptr;     /* not the way to declare a pointer */ 

Why not? Because it is not enough to say that a variable is a pointer. You also have to say what kind of variable the pointer points to. The reason for this is that different variable types take up different amounts of storage, and some pointer operations require knowledge of that storage size . Also, the program has to know what kind of data is stored at the address. A long and a float might use the same amount of storage, but they store numbers quite differently. Here's how pointers are declared:

 int * pi;         /* pi is a pointer to an integer variable  */ char * pc;        /* pc is a pointer to a character variable */ float * pf, * pg; /* pf, pg are pointers to float variables  */ 

The type specification identifies the type of variable pointed to, and the asterisk ( * ) identifies the variable itself as a pointer. The declaration int * pi; says that pi is a pointer and that *pi is type int (see Figure 9.5).

Figure 9.5. Declaring and using pointers
graphics/09fig05.jpg

The space between the * and the pointer name is optional. Often, programmers use the space in a declaration and omit it when dereferencing a variable.

The value ( *pc ) of what pc points to is of type char . What of pc itself? We describe it as being of type "pointer to char ." Its value, being an address, is an unsigned integer on most systems. Therefore, on most systems, you can use the %u format to print the value of pc . As mentioned earlier, that need not hold true universally , so ANSI C provides the %p form specifically for pointers. Also, as the next chapter explains, the allowed operations for a pointer are different from those for an unsigned integer.

Using Pointers to Communicate Between Functions

We have touched only the surface of the rich and fascinating world of pointers, but our concern here is using pointers to solve our communication problem. Listing 9.16 shows a program that uses pointers to make the interchange() function work. Let's look at it, run it, and then try to understand how it works.

Listing 9.16 The swap3.c program.
 /* swap3.c -- using pointers to make swapping work */ #include <stdio.h> void interchange(int * u, int * v); int main(void) {     int x = 5, y = 10;     printf("Originally x = %d and y = %d.\n", x, y);     interchange(&x, &y);  /* send addresses to function  */     printf("Now x = %d and y = %d.\n", x, y);     return 0; } void interchange(int * u, int * v) {     int temp;     temp = *u;       /* temp gets value that u points to */     *u = *v;     *v = temp; } 

After all this trouble, does Listing 9.16 really work?

 Originally x = 5 and y = 10. Now x = 10 and y = 5. 

Yes, it works.

Now, let's see how Listing 9.16 works. First, the function call looks like this:

 interchange(&x, &y); 

Instead of transmitting the values of x and y , you are transmitting their addresses . That means the formal arguments u and v appearing in the prototype and in the definition of interchange() will have addresses as their values. Therefore, they should be declared as pointers. Because x and y are integers, u and v are pointers to integers, so declare them as follows :

 void interchange (int * u, int * v) 

Next, in the body of the function, declare

 int temp; 

to provide the temporary storage you need. You want to store the value of x in temp , so you say

 temp = *u; 

Remember, u has the value &x , so u points to x . This means that *u gives you the value of x , which is what you want. You don't want to write

 temp = u;   /* NO */ 

because that would assign temp the address of x rather than its value, and you are trying to interchange values, not addresses.

Similarly, to assign the value of y to x , use

 *u = *v; 

which translates to

 x = y; 

Let's summarize what this example does. You want a function that alters the values x and y . By passing the function the addresses of x and y , you give interchange() access to those variables. Using pointers and the * operator, the function can examine the values stored at those locations and change them.

There are a couple of variants you should know about. The pre-ANSI form for the function heading is this:

 void interchange(u, v) int * u, * v; 

You can omit the variable names in the ANSI prototype. Then the prototype declaration looks like this:

 void interchange(int *, int *); 

More generally, you can communicate two kinds of information about a variable to a function. If you use a call of the form

 function1(x); 

you transmit the value of x . If you use a call of the form

 function2(&x); 

you transmit the address of x . The first form requires that the function definition include a formal argument of the same type as x .

 int function1(int num) 

The second form requires that the function definition include a formal argument that is a pointer to the right type:

 int function2(int * ptr) 

Use the first form if the function needs a value for some calculation or action. Use the second form if the function needs to alter variables in the calling function. You have been doing this all along with the scanf() function. When you want to read in a value for a variable num , for example, you use scanf("%d", &num) . That function reads a value and then uses the address you give it to store the value.

Pointers enable you to get around the fact that the variables of interchange() were local. They let that function reach out into main() and alter what was stored there.

Pascal and Modula-2 users might recognize the first form as being the same as Pascal's value parameter and the second form as being similar (but not identical) to Pascal's variable parameter. BASIC users might find the whole setup a bit unsettling. If this section seems strange to you, be assured that a little practice will make at least some uses of pointers seem simple, normal, and convenient (see Figure 9.6).

Figure 9.6. Names, addresses, and values in a byte-addressable system.
graphics/09fig06.jpg

Variables: Names, Addresses, and Values

The preceding discussion of pointers has hinged on the relationships between the names, addresses, and values of variables. Let's discuss these matters further.

When you write a program, you think of a variable as having two attributes: a name and a value. (There are other attributes, including type, but that's another matter.) After the program has been compiled and loaded, the computer also thinks of the same variable as having two attributes: an address and a value. An address is the computer's version of a name.

In many languages, the address is the computer's business, concealed from the programmer. In C, however, you can access the address through the & operator.

&barn is the address of the variable barn .

You can get the value from the name just by using the name.

printf("%d\n", barn) prints the value of barn.

You can get the value from the address by using the * operator.

Given pbarn = &barn; , then *pbarn is the value stored at address &barn .

In short, a regular variable makes the value the primary quantity and the address a derived quantity, via the & operator. A pointer variable makes the address the primary quantity and the value a derived quantity, via the * operator.

Although you can print an address to satisfy your curiosity , that is not the main use for the & operator. More important, using & , * , and pointers enables you to manipulate addresses and their contents symbolically, as in swap3.c (refer to Listing 9.16).

Summary: Functions

Form:

A typical function definition has this form:

 name(argument list) argument declarations function body 

The presence of the argument list and declarations is optional. Variables other than the arguments are declared within the body, which is bounded by braces.

ANSI C encourages the following form:

 name(argument declaration list) function body 

The argument declaration list is a comma-separated list of variable declarations.

Examples:

 int diff(x,y)     /* function name and argument list */ int x,y;          /* declare arguments               */ {                 /* begin function body             */   int z;          /* declare local variable          */   z = x - y;   return z; }                 /* end function body               */ int diff(int x, int y)     /* ANSI version                */ {                          /* begin function body         */   int z;                   /* declare local variable      */   z = x - y;   return z; }                         /* end function body           */ 

Communicating Values:

Arguments are used to convey values from the calling function to the function. If variables a and b have the values 5 and 2 , then the call

 c = diff(a,b); 

transmits 5 and 2 to the variables x and y . The values 5 and 2 are called actual arguments, and the diff() variables x and y are called formal arguments. The keyword return communicates one value from the function to the calling function. In this example, c receives the value of z , which is 3 . A function ordinarily has no effect on the variables in a calling function.

To directly affect variables in the calling function, use pointers as arguments. This might be necessary if you want to communicate more than one value back to the calling function.

Function Type:

Functions must have the same type as the value they return. Functions are assumed to be type int . If a function is another type, it must be declared as such in the calling function and in the function definition.

Example:

 int main(void) {   double q, x, duff();  /* declare in calling function   */   int n;   ...    q = duff(x,n);   ...  } double duff(u, k)      /* declare in function definition */ double u; int k; {   double tor; ...   return tor;          /* returns a double value         */ } 
I l @ ve RuBoard


C++ Primer Plus
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2000
Pages: 314
Authors: Stephen Prata

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net