Then the two pointers elbuod and elbuod + 20 define the range. First, elbuod, being the name of the array, points to the first element. The expression elbuod + 19 points to the last element (that is, elbuod[19]), so elbuod + 20 points to one past the end of the array. Passing a range to a function tells it which elements to process. Listing 7.8 modifies Listing 7.6 to use two pointers to specify a range.
Listing 7.8. arrfun4.cpp
// arrfun4.cpp -- functions with an array range
#include
const int ArSize = 8;
int sum_arr(const int * begin, const int * end);
int main()
{
using namespace std;
int cookies[ArSize] = {1,2,4,8,16,32,64,128};
// some systems require preceding int with static to
// enable array initialization
int sum = sum_arr(cookies, cookies + ArSize);
cout << "Total cookies eaten: " << sum << endl;
sum = sum_arr(cookies, cookies + 3); // first 3 elements
cout << "First three eaters ate " << sum << " cookies.\n";
sum = sum_arr(cookies + 4, cookies + 8); // last 4 elements
cout << "Last four eaters ate " << sum << " cookies.\n";
return 0;
}
// return the sum of an integer array
int sum_arr(const int * begin, const int * end)
{
const int * pt;
int total = 0;
for (pt = begin; pt != end; pt++)
total = total + *pt;
return total;
}
Here’s the output of the program in Listing 7.8:
Total cookies eaten: 255
First three eaters ate 7 cookies.
Last four eaters ate 240 cookies.
Program Notes
In Listing 7.8, notice the for loop in the sum_array() function:
for (pt = begin; pt != end; pt++)
total = total + *pt;
It sets pt to point to the first element to be processed (the one pointed to by begin) and adds *pt (the value of the element) to total. Then the loop updates pt by incrementing it, causing it to point to the next element. The process continues as long as pt != end. When pt finally equals end, it’s pointing to the location following the last element of the range, so the loop halts.
Second, notice how the different function calls specify different ranges within the array:
int sum = sum_arr(cookies, cookies + ArSize);
...
sum = sum_arr(cookies, cookies + 3); // first 3 elements
...
sum = sum_arr(cookies + 4, cookies + 8); // last 4 elements
The pointer value cookies + ArSize points to the location following the last element. (The array has ArSize elements, so cookies[ArSize - 1] is the last element, and its address is cookies + ArSize - 1.) So the range cookies, cookies + ArSize specifies the entire array. Similarly, cookies, cookies + 3 specifies the first three elements, and so on.
Note, by the way, that the rules for pointer subtraction imply that, in sum_arr(), the expression end - begin is an integer value equal to the number of elements in the range.
Also note that it’s important to pass the pointers in the correct order; the code assumes that end comes after begin.
Pointers and const
Using const with pointers has some subtle aspects (pointers always seem to have subtle aspects), so let’s take a closer look. You can use the const keyword two different ways with pointers. The first way is to make a pointer point to a constant object, and that prevents you from using the pointer to change the pointed-to value. The second way is to make the pointer itself constant, and that prevents you from changing where the pointer points. Now for the details.
First, let’s declare a pointer pt that points to a constant:
int age = 39;
const int * pt = &age
This declaration states that pt points to a const int (39, in this case). Therefore, you can’t use pt to change that value. In other words, the value *pt is const and cannot be modified:
*pt += 1; // INVALID because pt points to a const int
cin >> *pt; // INVALID for the same reason
Now for a subtle point. This declaration for pt doesn’t necessarily mean that the value it points to is really a constant; it just means the value is a constant insofar as pt is concerned. For example, pt points to age, and age is not const. You can change the value of age directly by using the age variable, but you can’t change the value indirectly via the pt pointer:
*pt = 20; // INVALID because pt points to a const int
age = 20; // VALID because age is not declared to be const
Previous examples have assigned the address of a regular variable to a regular pointer. This example assigns the address of a regular variable to a pointer-to-const. That leaves two other possibilities: assigning the address of a const variable to a pointer-to-const and assigning the address of a const to a regular pointer. Are they both possible? The first is, and the second isn’t:
const float g_earth = 9.80;
const float * pe = &g_earth; // VALID
const float g_moon = 1.63;
float * pm = &g_moon; // INVALID