There is a close association between pointers and arrays. “Arrays and Strings,” how array elements are accessed. The following program, ARRNOTE, provides a review.
// arrnote.cpp // array accessed with array notation #include <iostream> using namespace std; int main() { //array int intarray[5] = { 31, 54, 77, 52, 93 }; for(int j=0; j<5; j++) //for each element, cout << intarray[j] << endl; //print value return 0; }
The cout statement prints each array element in turn. For instance, when j is 3, the expression intarray[j] takes on the value intarray[3] and accesses the fourth array element, the integer 52. Here’s the output of ARRNOTE:
31
54
77
52
93
Surprisingly, array elements can be accessed using pointer notation as well as array notation. The next example, PTRNOTE, is similar to ARRNOTE except that it uses pointer notation.
// ptrnote.cpp // array accessed with pointer notation #include <iostream> using namespace std; int main() { //array int intarray[5] = { 31, 54, 77, 52, 93 }; for(int j=0; j<5; j++) //for each element, cout << *(intarray+j) << endl; //print value return 0; }
The expression *(intarray+j) in PTRNOTE has exactly the same effect as intarray[j] in ARRNOTE, and the output of the programs is identical. But how do we interpret the expression *(intarray+j)? Suppose j is 3, so the expression is equivalent to *(intarray+3). We want this to represent the contents of the fourth element of the array (52). Remember that the name of an array is its address. The expression intarray+j is thus an address with something added to it. You might expect that intarray+3 would cause 3 bytes to be added to intarray. But that doesn’t produce the result we want: intarray is an array of integers, and 3 bytes into this array is the middle of the second element, which is not very useful. We want to obtain the fourth integer in the array, not the fourth byte. (This figure assumes 2-byte integers.)
The C++ compiler is smart enough to take the size of the data into account when it performs arithmetic on data addresses. It knows that intarray is an array of type int because it was declared that way. So when it sees the expression intarray+3, it interprets it as the address of the fourth integer in intarray, not the fourth byte.
But we want the value of this fourth array element, not the address. To take the value, we use the dereference operator (*). The resulting expression, when j is 3, is *(intarray+3), which is the content of the fourth array element, or 52.
Now we see why a pointer declaration must include the type of the variable pointed to. The compiler needs to know whether a pointers and arrays is a pointer to int or a pointer to double so that it can perform the correct arithmetic to access elements of the array. It multiplies the index value by 2 in the case of type int, but by 8 in the case of double.
Pointer Constants and Pointer Variables
Suppose that, instead of adding j to intarray to step through the array addresses, you wanted to use the increment operator. Could you write *(intarray++)?
The answer is no, and the reason is that you can’t increment a constant (or indeed change it in any way). The expression intarray is the address where the system has chosen to place your array, and it will stay at this address until the program terminates. intarray is a pointer constant. You can’t say intarray++ any more than you can say 7++. (In a multitasking system, variable addresses may change during program execution. An active program may be swapped out to disk and then reloaded at a different memory location. However, this process is invisible to your program.)
But while you can’t increment an address, you can increment a pointers and arrays that holds an address. The next example, PTRINC, shows how:
// ptrinc.cpp // array accessed with pointer #include <iostream> using namespace std; int main() { int intarray[] = { 31, 54, 77, 52, 93 }; //array int* ptrint; //pointer to int ptrint = intarray; //points to intarray for(int j=0; j<5; j++) //for each element, cout << *(ptrint++) << endl; //print value return 0; }
Here we define a pointer to int ptrint and give it the value intarray, the address of the array. Now we can access the contents of the array elements with the expression *(ptrint++)
The variable ptrint starts off with the same address value as intarray, thus allowing the first array element, intarray[0], which has the value 31, to be accessed as before. But, because ptrint is a variable and not a constant, it can be incremented. After it is incremented, it points to the second array element, intarray[1]. The expression *(ptrint++) then represents the contents of the second array element, or 54. The loop causes the expression to access each array element in turn. The output of PTRINC is the same as that for PTRNOTE.
Read More Topics |
Common programming error |
Virtual function in C++ |
Abstract class in C++ |
Organisation of the network layer |