int diff = pe - pt;     // diff is 7, the separation between

                        // tacos[8] and tacos[1]

Dynamic Binding and Static Binding for Arrays

You can use an array declaration to create an array with static binding—that is, an array whose size is set during the compilation process:

int tacos[10]; // static binding, size fixed at compile time

You use the new [] operator to create an array with dynamic binding (a dynamic array)—that is, an array that is allocated and whose size can be set during runtime. You free the memory with delete [] when you are done:

int size;

cin >> size;

int * pz = new int [size];   // dynamic binding, size set at run time

...

delete [] pz;                // free memory when finished

Array Notation and Pointer Notation

Using bracket array notation is equivalent to dereferencing a pointer:

tacos[0] means *tacos means the value at address tacos

tacos[3] means *(tacos + 3) means the value at address tacos + 3

This is true for both array names and pointer variables, so you can use either pointer notation or array notation with pointers and array names.

Here are some examples:

int * pt = new int [10];   // pt points to block of 10 ints

*pt = 5;                   // set element number 0 to 5

pt[0] = 6;                 // reset element number 0 to 6

pt[9] = 44;                // set tenth element (element number 9) to 44

int coats[10];

*(coats + 4) = 12;         // set coats[4] to 12

Pointers and Strings

The special relationship between arrays and pointers extends to C-style strings. Consider the following code:

char flower[10] = "rose";

cout << flower << "s are red\n";

The name of an array is the address of its first element, so flower in the cout statement is the address of the char element containing the character r. The cout object assumes that the address of a char is the address of a string, so it prints the character at that address and then continues printing characters until it runs into the null character (\0). In short, if you give cout the address of a character, it prints everything from that character to the first null character that follows it.

The crucial element here is not that flower is an array name but that flower acts as the address of a char. This implies that you can use a pointer-to-char variable as an argument to cout also because it, too, is the address of a char. Of course, that pointer should point to the beginning of a string. We’ll check that out in a moment.

But what about the final part of the preceding cout statement? If flower is actually the address of the first character of a string, what is the expression "s are red\n"? To be consistent with cout’s handling of string output, this quoted string should also be an address. And it is, for in C++ a quoted string, like an array name, serves as the address of its first element. The preceding code doesn’t really send a whole string to cout; it just sends the string address. This means strings in an array, quoted string constants, and strings described by pointers are all handled equivalently. Each is really passed along as an address. That’s certainly less work than passing each and every character in a string.

Note

With cout and with most C++ expressions, the name of an array of char, a pointer-to-char, and a quoted string constant are all interpreted as the address of the first character of a string.

Listing 4.20 illustrates the use of the different forms of strings. It uses two functions from the string library. The strlen() function, which you’ve used before, returns the length of a string. The strcpy() function copies a string from one location to another. Both have function prototypes in the cstring header file (or string.h, on less up-to-date implementations). The program also uses comments to showcase some pointer misuses that you should try to avoid.

Listing 4.20. ptrstr.cpp

// ptrstr.cpp -- using pointers to strings

#include

#include               // declare strlen(), strcpy()

int main()

{

    using namespace std;

    char animal[20] = "bear";   // animal holds bear

    const char * bird = "wren"; // bird holds address of string

    char * ps;                  // uninitialized

    cout << animal << " and ";  // display bear

    cout << bird << "\n";       // display wren

    // cout << ps << "\n";      //may display garbage, may cause a crash

    cout << "Enter a kind of animal: ";

    cin >> animal;              // ok if input < 20 chars

    // cin >> ps; Too horrible a blunder to try; ps doesn't

    //            point to allocated space

    ps = animal;                // set ps to point to string

    cout << ps << "!\n";       // ok, same as using animal

    cout << "Before using strcpy():\n";

    cout << animal << " at " << (int *) animal << endl;

    cout << ps << " at " << (int *) ps << endl;

    ps = new char[strlen(animal) + 1];  // get new storage

    strcpy(ps, animal);         // copy string to new storage

    cout << "After using strcpy():\n";

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги