33
C++ A Beginner’s Guide by Herbert Schildt
Ask the Expert
Q:
Are pointers and arrays interchangeable?
A:
As the preceding few pages have shown, pointers and arrays are strongly related and are
interchangeable in many cases. For example, a pointer that points to the beginning of an array can
access that array using either pointer arithmetic or array-style indexing. However, pointers and arrays
are not completely interchangeable. For example, consider this fragment:
int nums[10]; int i;
for(i=0; i<10; i++) { *nums = i; // this is OK nums++; // ERROR -- cannot modify nums
}
Here, nums is an array of integers. As the comments describe, while it is perfectly acceptable to apply
the * operator to nums (which is a pointer operation), it is illegal to modify nums’ value. The reason for
this is that nums is a constant that points to the beginning of an array. Thus, you cannot increment it.
More generally, while an array name without an index does generate a pointer to the beginning of an
array, it cannot be changed.
Although an array name generates a pointer constant, it can still take part in pointer-style expressions,
as long as it is not modified. For example, the following is a valid statement that assigns nums[3] the
value 100:
*(nums+3) = 100; // This is OK because nums is not changed
String Constants
34
C++ A Beginner’s Guide by Herbert Schildt
You might be wondering how string constants, like the one in the fragment shown here, are handled by
C++:
cout << strlen("Xanadu");
The answer is that when the compiler encounters a string constant, it stores it in the program’s string
table and generates a pointer to the string. Thus, “Xanadu” yields a pointer to its entry in the string
table. Therefore, the following program is perfectly valid and prints the phrase Pointers add power to
C++.:
In this program, the characters that make up a string constant are stored in the string table, and ptr is
assigned a pointer to the string in that table.
Since a pointer into your program’s string table is generated automatically whenever a string constant is
used, you might be tempted to use this fact to modify the contents of the string table. However, this is
usually not a good idea because many C++ compilers create optimized tables in which one string
constant may be used at two or more different places in your program. Thus, changing a string may
cause undesired side effects.
Earlier it was mentioned that comparing one pointer to another is meaningful only if the two pointers
point to a common object, such as an array. Now that you understand how pointers and arrays relate,
you can apply pointer comparisons to streamline some types of algorithms. In this project, you will see
an example. The program developed here reverses the contents of a string, in place. Thus, instead of
copying the string back-to-front into another array, it reverses the contents of the string inside the array
that holds it. The program uses two pointer variables to accomplish this. One initially points to the
beginning of a string, and the other initially points to the last character in the string. A loop is set up that
continues to run as long as the start pointer is less than the end pointer. Each time through the loop, the
characters pointed to by the pointers are swapped and the pointers are advanced. When the start
pointer is greater than or equal to the end pointer, the string has been reversed.
35
C++ A Beginner’s Guide by Herbert Schildt
Step by Step
1.
Create a file called StrRev.cpp.
2.
Begin by adding these lines to the file:
The string to be reversed is contained in str. The pointers start and end will be used to access the string.
3.
Add these lines, which display the original string, obtain the string’s length, and set the initial values
for the start and end pointers:
cout << "Original: " << str << "\n";
len = strlen(str);
start = str; end = &str[len-1];
Notice that end points to the last character in the string, not the null terminator.
4.
Add the code that reverses the string:
36
C++ A Beginner’s Guide by Herbert Schildt
The process works like this. As long as the start pointer points to a memory location that is less than the
end pointer, the loop iterates. Inside the loop, the characters being pointed to by start and end are
swapped. Then start is incremented and end is decremented. When end is greater than or equal to start,
all of the characters in the string have been reversed. Since both start and end point into the same
array, their comparison is meaningful.
5.
Here is the complete StrRev.cpp program:
37
C++ A Beginner’s Guide by Herbert Schildt
The output from the program is shown here:
Original: this is a test
Reversed: tset a si siht
Arrays of Pointers
Pointers can be arrayed like any other data type. For example, the declaration for an int pointer array of
size 10 is
int *pi[10];
38
C++ A Beginner’s Guide by Herbert Schildt
Here, pi is an array of ten integer pointers. To assign the address of an int variable called var to the third
element of the pointer array, you would write
int var;
pi[2] = &var;
Remember, pi is an array of int pointers. The only thing that the array elements can hold are the
addresses of integer values—not the values themselves. To find the value of var, you would write
*pi[2]
Like other arrays, arrays of pointers can be initialized. A common use for initialized pointer arrays is to
hold pointers to strings. Here is an example that uses a two-dimensional array of character pointers to
implement a small dictionary:
39
C++ A Beginner’s Guide by Herbert Schildt
Here is a sample run:
Enter word: network
An interconnected group of computers.
When the array dictionary is created, it is initialized with a set of words and their meanings. Recall, C++
stores all string constants in the string table associated with your program, so the array need only store
pointers to the strings. The program works by testing the word entered by the user against the strings
stored in the dictionary. If a match is found, the meaning is displayed. If no match is found, an error
message is printed.
Notice that dictionary ends with two null strings. These mark the end of the array. Recall that a null
string contains only the terminating null character. The for loop runs until the first character in a string is
null. This condition is tested with this expression:
*dictionary[i][0]
The array indices specify a pointer to a string. The * obtains the character at that location. If this
character is null, then the expression is false and the loop terminates. Otherwise, the expression is true
and the loop continues.
The Null Pointer Convention
After a pointer is declared, but before it has been assigned, it will contain an arbitrary value. Should you
try to use the pointer prior to giving it a value, you will probably crash your program. While there is no
sure way to avoid using an uninitialized pointer, C++ programmers have adopted a procedure that helps
prevent some errors. By convention, if a pointer contains the null (zero) value, it is assumed to point to
nothing. Thus, if all unused pointers are given the null value and you avoid the use of a null pointer, you
can avoid the accidental misuse of an uninitialized pointer. This is a good practice to follow.
40
C++ A Beginner’s Guide by Herbert Schildt
Any type of pointer can be initialized to null when it is declared. For example, the following initializes p
to null:
float *p = 0; // p is now a null pointer
To check for a null pointer, use an if statement, like one of these:
if(p) // succeeds if p is not null
if(!p) // succeeds if p is null
Do'stlaringiz bilan baham: |