Pointers to Arrays

I l @ ve RuBoard

Pointers to Arrays

Pointers, as you,, may recall from Chapter 9, "Functions," provide a symbolic way to use addresses. Because the hardware instructions of computing machines rely heavily on addresses, pointers enable you to express yourself in a way that is close to how the machine expresses itself. This correspondence makes programs with pointers efficient. In particular, pointers offer an efficient way to deal with arrays. Indeed, as you will see, array notation is simply a disguised use of pointers.

An example of this disguised use is that an array name is also the address of the first element of an array. That is, if flizny is an array, then the following is true:

 flizny == &flizny[0] 

Both flizny and &flizny[0] represent the memory address of that first element. (Recall that & is the address operator). Both are constants because they remain fixed for the duration of the program. However, they can be assigned as values to a,,, pointer variable , and you can change the value of a variable, as Listing 10.5 shows. Notice what happens to the value of a pointer when you add a number to it. (Recall that the %p specifier for the pointers typically displays hexadecimal values.)

Listing 10.5 The code pnt_add.c program.
 /* pnt_add.c -- pointer addition */ #include <stdio.h> #define SIZE 4 int main(void) {   short dates [SIZE], * pti, index;   double bills[SIZE], * ptf;   pti = dates;    /* assign address of array to pointer */   ptf = bills;   printf("%23s %10s\n", "short", "double");   for (index = 0; index < SIZE; index ++)        printf("pointers + %d: %10p %10p\n",                index, pti + index, ptf + index);   return 0; } 

Here is the output:

 short     double pointers + 0:   0064FDC8   0064FDD8 pointers + 1:   0064FDCA   0064FDE0 pointers + 2:   0064FDCC   0064FDE8 pointers + 3:   0064FDCE   0064FDF0 

The second line prints the beginning addresses of the two arrays, and the next line gives the result of adding 1 to the address, and so on. Note that A is the hexadecimal digit for 10, C is the digit for 12, and E is the digit for 14. So, for example, 8 + 2 is A. What?

 0064FDC8 + 1 = 0064FDCA? 0064FDE0 + 1 = 0064FDE8? 

Pretty crazy? Like a fox! Our system is addressed by individual bytes, but type short uses 2 bytes and type double uses 4 bytes. What is happening here is that when you say "add 1 to a pointer," C adds one storage unit . For arrays, that means the address is increased to the address of the next element , not just the next byte (see Figure 10.1). This is one reason you have to declare what sort of object a pointer points to. The address is not enough because the computer needs to know how many bytes are used to store the object. (This is true even for pointers to scalar variables ; otherwise , the *pt operation to fetch the value wouldn't work correctly.)

Figure 10.1. An array and pointer addition.
graphics/10fig01.jpg

Now we can define more clearly what is meant by pointer-to- int or pointer-to- float or pointer to any other data object:

  • The value of a pointer is the address of the object to which it points. How the address is represented internally is hardware dependent. Many computers, including PCs and VAXs, are byte addressable , meaning that each byte in memory is numbered sequentially. Here, the address of a large object, such as type double variable, typically is the address of the first byte of the object.

  • Applying the * operator to a pointer yields the value stored in the pointed-to object.

  • Adding 1 to the pointer increases its value by the size, in bytes, of the pointed-to object.

As a result of C's cleverness , you have the following equalities:

 dates +2 == &date[2]          /* same address */ *(dates + 2) == dates[2]      /* same value   */ 

These relationships sum up the close connection between arrays and pointers. They mean you can use a pointer to identify an individual element of an array and to get its value. In essence, you have two different notations for the same thing. Indeed, the C language standard describes array notation in terms of pointers, so the pointer approach is the more basic of the two.

Incidentally, don't confuse *(dates+2) with *dates+2 . The indirection operator ( * ) binds more tightly (has higher precedence) than + , so the latter means (*dates)+2 .

 *(dates +2)       /* value of the 3rd element of dates        */ *dates +2         /* 2 added to the value of the 1st element  */ 

The relationship between arrays and pointers means that you can often use either approach when writing a program. Listing 10.6, for instance, produces the same output as Listing 10.1 when compiled and run.

Listing 10.6 The day_mon3.c program.
 /* day_mon3.c -- uses pointer notation */ #include <stdio.h> #define MONTHS 12 int main(void) {   int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31};   int index;   for (index = 0; index < MONTHS; index++)      printf("Month %d has %d days.\n", index +1,              *(days + index));   // same as days[index]   return 0; } 

Here, days is the address of the first element of the array, days + index is the address of element days[index] , and *(days + index) is the value of that element, just as days[index] is. The loop references each element of the array in turn and prints the contents of what it finds.

Is there an advantage to writing the program this way? Not really. The point to Listing 10.6 is that pointer notation and array notation are two equivalent methods . This example shows you can use pointer notation with arrays. The reverse is also true; you can use array notation with pointers. This turns out to be important when you have a function with an array as an argument.

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