Recall that the const qualifier enables the programmer to inform the compiler that the value of a particular variable should not be modified.
Portability Tip 8.2
Although const is well defined in ANSI C and C++, some compilers do not enforce it properly. So a good rule is, "Know your compiler." |
Over the years, a large base of legacy code was written in early versions of C that did not use const, because it was not available. For this reason, there are great opportunities for improvement in the software engineering of old (also called "legacy") C code. Also, many programmers currently using ANSI C and C++ do not use const in their programs, because they began programming in early versions of C. These programmers are missing many opportunities for good software engineering.
Many possibilities exist for using (or not using) const with function parameters. How do you choose the most appropriate of these possibilities? Let the principle of least privilege be your guide. Always award a function enough access to the data in its parameters to accomplish its specified task, but no more. This section discusses how to combine const with pointer declarations to enforce the principle of least privilege.
Chapter 6 explained that when a function is called using pass-by-value, a copy of the argument (or arguments) in the function call is made and passed to the function. If the copy is modified in the function, the original value is maintained in the caller without change. In many cases, a value passed to a function is modified so the function can accomplish its task. However, in some instances, the value should not be altered in the called function, even though the called function manipulates only a copy of the original value.
For example, consider a function that takes a one-dimensional array and its size as arguments and subsequently prints the array. Such a function should loop through the array and output each array element individually. The size of the array is used in the function body to determine the highest subscript of the array so the loop can terminate when the printing completes. The size of the array does not change in the function body, so it should be declared const. Of course, because the array is only being printed, it, too, should be declared const. This is especially important because an entire array is always passed by reference and could easily be changed in the called function.
Software Engineering Observation 8.2
If a value does not (or should not) change in the body of a function to which it is passed, the parameter should be declared const to ensure that it is not accidentally modified. |
If an attempt is made to modify a const value, a warning or an error is issued, depending on the particular compiler.
Error-Prevention Tip 8.2
Before using a function, check its function prototype to determine the parameters that it can modify. |
There are four ways to pass a pointer to a function: a nonconstant pointer to nonconstant data (Fig. 8.10), a nonconstant pointer to constant data (Fig. 8.11 and Fig. 8.12), a constant pointer to nonconstant data (Fig. 8.13) and a constant pointer to constant data (Fig. 8.14). Each combination provides a different level of access privileges.
Figure 8.10. Converting a string to uppercase.
(This item is displayed on page 413 in the print version)
1 // Fig. 8.10: fig08_10.cpp 2 // Converting lowercase letters to uppercase letters 3 // using a non-constant pointer to non-constant data. 4 #include 5 using std::cout; 6 using std::endl; 7 8 #include // prototypes for islower and toupper 9 using std::islower; 10 using std::toupper; 11 12 void convertToUppercase( char * ); 13 14 int main() 15 { 16 char phrase[] = "characters and $32.98"; 17 18 cout << "The phrase before conversion is: " << phrase; 19 convertToUppercase( phrase ); 20 cout << " The phrase after conversion is: " << phrase << endl; 21 return 0; // indicates successful termination 22 } // end main 23 24 // convert string to uppercase letters 25 void convertToUppercase( char *sPtr ) 26 { 27 while ( *sPtr != ' |