Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

Chapter 9: Taking a Second Look at C++ Pointers 129

int main(int nNumberofArgs, char* pszArgs[])

{

int array[] = {4, 3, 2, 1}; displayArray(array, 4);

//wait until user is ready before terminating program

//to allow the user to see the program results system(“PAUSE”);

return 0;

}

The output from this program is

The value of the array is:

0:4

1:3

2:2

3:1

Press any key to continue . . .

You may think this pointer conversion is silly; however, the pointer version of displayArray() is actually more common among C++ programmers in the know than the array version. For some reason, C++ programmers don’t seem to like arrays.

The use of pointers to access arrays is nowhere more common than in the accessing of character arrays.

Expanding pointer operations to a string

A null terminated string is simply a character array whose last character is a null. C++ uses the null character at the end to serve as a terminator. This null terminated array serves as a quasi-variable type of its own. (See Chapter 7 for an explanation of string arrays.) Often C++ programmers use character point­ ers to manipulate such strings. The following code examples compare this technique to the earlier technique of indexing in the array.

Character pointers enjoy the same relationship with a character array that any other pointer and array share. However, the fact that strings end in a terminat­ ing null makes them especially amenable to pointer-based manipulation, as shown in the following DisplayString() program:

// DisplayString - display an array of characters both // using a pointer and an array index #include <cstdio>

#include <cstdlib> #include <iostream>

130 Part II: Becoming a Functional C++ Programmer

using namespace std;

int main(int nNumberofArgs, char* pszArgs[])

{

//declare a string char* szString = “Randy”;

cout << “The array is ‘“ << szString << “‘“ << endl;

//display szString as an array

cout << “Display the string as an array: “; for(int i = 0; i < 5; i++)

{

cout << szString[i];

}

cout << endl;

//now using typical pointer arithmetic cout << “Display string using a pointer: “; char* pszString = szString; while(*pszString)

{

cout << *pszString; pszString++;

}

cout << endl;

//wait until user is ready before terminating program

//to allow the user to see the program results system(“PAUSE”);

return 0;

}

The program first makes its way through the array szString by indexing into the array of characters. The for loop chosen stops when the index reaches 5, the length of the string.

The second loop displays the same string using a pointer. The program sets the variable pszString equal to the address of the first character in the array. It then enters a loop that will continue until the char pointed at by pszString is equal to false — in other words, until the character is a null.

The integer value 0 is interpreted as false — all other values are true.

The program outputs the character pointed at by pszString and then incre­ ments the pointer so that it points to the next character in the string before being returned to the top of the loop.

The dereference and increment can be (and usually are) combined into a single expression as follows:

cout << *pszString++;

Chapter 9: Taking a Second Look at C++ Pointers 131

The output of the program appears as follows:

The array is ‘Randy’

Display the string as an array: Randy

Display string using a pointer: Randy

Press any key to continue . . .

Justifying pointer-based string manipulation

The sometimes-cryptic nature of pointer-based manipulation of character strings might lead the reader to wonder, “Why?” That is, what advantage does the char* pointer version have over the easier-to-read index version?

The answer is partially (pre-)historic and partially human nature. When C, the progenitor to C++, was invented, compilers were pretty simplistic. These compilers could not perform the complicated optimizations that modern compilers can. As complicated as it might appear to the human reader, a statement such as *pszString++ could be converted into an amazingly small number of machine level instructions even by a stupid compiler.

Older computer processors were not very fast by today’s standards. In the old days of C, saving a few computer instructions was a big deal. This gave C a big advantage over other languages of the day, notably Fortran, which did not offer pointer arithmetic.

In addition to the efficiency factor, programmers like to generate clever pro­ gram statements. After C++ programmers learn how to write compact and cryptic but efficient statements, there is no getting them back to accessing arrays with indices.

Do not generate complex C++ expressions in order to create a more efficient program. There is no obvious relationship between the number of C++ state­ ments and the number of machine instructions generated.

Applying operators to pointer types other than char

It is not too hard to convince yourself that szTarget + n points to szTarget [n] when szTarget is an array of chars. After all, a char occupies a single byte. If szTarget is stored at 0x100, the sixth element is located at 0x105.

132 Part II: Becoming a Functional C++ Programmer

It is not so obvious that pointer addition works in exactly the same way for an int array because an int takes 4 bytes for each char’s 1 byte (at least it does on a 32-bit Intel processor). If the first element in intArray were located at 0x100, the sixth element would be located at 0x114 (0x100 + (5 * 4) = 0x114) and not 0x104.

Fortunately for us, array + n points at array[n] no matter how large a single element of array might be. C++ takes care of the element size for us — it’s clever that way.

Once again, the dusty old house analogy works here as well. (I mean dusty analogy, not dusty house.) The third house down from 123 Main is 126 Main, no matter how large the building might be, even if it’s a hotel.

Contrasting a pointer with an array

There are some differences between indexing into an array and using a pointer. For one, the array allocates space for the data, whereas the pointer does not, as shown here:

void arrayVsPointer()

{

//allocate storage for 128 characters char charArray[128];

//allocate space for a pointer but not for

//the thing pointed at

char* pArray;

}

Here charArray allocates room for 128 characters. pArray allocates only 4 bytes — the amount of storage required by a pointer.

The following function does not work:

void arrayVsPointer()

{

//this works fine char charArray[128]; charArray[10] = ‘0’;

*(charArray + 10) = ‘0’;

//this does not work char* pArray; pArray[10] = ‘0’; *(pArray + 10) = ‘0’;

}