Passing Arrays to Functions

To pass an array argument to a function, specify the name of the array without any brackets. For example, if array hourlyTemperatures has been declared as

int hourlyTemperatures[ 24 ];

the function call

modifyArray( hourlyTemperatures, 24 );

passes array hourlyTemperatures and its size to function modifyArray. When passing an array to a function, the array size is normally passed as well, so the function can process the specific number of elements in the array. (Otherwise, we would need to build this knowledge into the called function itself or, worse yet, place the array size in a global variable.) In Section 7.11, when we present C++ Standard Library class template vector to represent a more robust type of array, you will see that the size of a vector is built inevery vector object "knows" its own size, which can be obtained by invoking the vector object's size member function. Thus, when we pass a vector object into a function, we will not have to pass the size of the vector as an argument.


C++ passes arrays to functions by referencethe called functions can modify the element values in the callers' original arrays. The value of the name of the array is the address in the computer's memory of the first element of the array. Because the starting address of the array is passed, the called function knows precisely where the array is stored in memory. Therefore, when the called function modifies array elements in its function body, it is modifying the actual elements of the array in their original memory locations.

Performance Tip 7.3

Passing arrays by reference makes sense for performance reasons. If arrays were passed by value, a copy of each element would be passed. For large, frequently passed arrays, this would be time consuming and would require considerable storage for the copies of the array elements.

Software Engineering Observation 7.3

It is possible to pass an array by value (by using a simple trick we explain in Chapter 22)this is rarely done.

Although entire arrays are passed by reference, individual array elements are passed by value exactly as simple variables are. Such simple single pieces of data are called scalars or scalar quantities. To pass an element of an array to a function, use the subscripted name of the array element as an argument in the function call. In Chapter 6, we showed how to pass scalars (i.e., individual variables and array elements) by reference with references. In Chapter 8, we show how to pass scalars by reference with pointers.

For a function to receive an array through a function call, the function's parameter list must specify that the function expects to receive an array. For example, the function header for function modifyArray might be written as

void modifyArray( int b[], int arraySize )

indicating that modifyArray expects to receive the address of an array of integers in parameter b and the number of array elements in parameter arraySize. The size of the array is not required between the array brackets. If it is included, the compiler ignores it. Because C++ passes arrays to functions by reference, when the called function uses the array name b, it will in fact be referring to the actual array in the caller (i.e., array hourlyTemperatures discussed at the beginning of this section).

Note the strange appearance of the function prototype for modifyArray

void modifyArray( int [], int );

This prototype could have been written

void modifyArray( int anyArrayName[], int anyVariableName );

but, as we learned in Chapter 3, C++ compilers ignore variable names in prototypes. Remember, the prototype tells the compiler the number of arguments and the type of each argument (in the order in which the arguments are expected to appear).

The program in Fig. 7.14 demonstrates the difference between passing an entire array and passing an array element. Lines 2223 print the five original elements of integer array a. Line 28 passes a and its size to function modifyArray (lines 4550), which multiplies each of a's elements by 2 (through parameter b). Then, lines 3233 print array a again in main. As the output shows, the elements of a are indeed modified by modifyArray. Next, line 36 prints the value of scalar a[ 3 ], then line 38 passes element a[ 3 ] to function modifyElement (lines 5458), which multiplies its parameter by 2 and prints the new value. Note that when line 39 again prints a[ 3 ] in main, the value has not been modified, because individual array elements are passed by value.

Figure 7.14. Passing arrays and individual array elements to functions.

(This item is displayed on pages 348 - 349 in the print version)

 1 // Fig. 7.14: fig07_14.cpp
 2 // Passing arrays and individual array elements to functions.
 3 #include 
 4 using std::cout;
 5 using std::endl;
 6
 7 #include 
 8 using std::setw;
 9
10 void modifyArray( int [], int ); // appears strange
11 void modifyElement( int ); 
12
13 int main()
14 {
15 const int arraySize = 5; // size of array a
16 int a[ arraySize ] = { 0, 1, 2, 3, 4 }; // initialize array a
17
18 cout << "Effects of passing entire array by reference:"
19 << "

The values of the original array are:
";
20
21 // output original array elements
22 for ( int i = 0; i < arraySize; i++ )
23 cout << setw( 3 ) << a[ i ];
24
25 cout << endl;
26
27 // pass array a to modifyArray by reference
28 modifyArray( a, arraySize ); 
29 cout << "The values of the modified array are:
";
30
31 // output modified array elements
32 for ( int j = 0; j < arraySize; j++ )
33 cout << setw( 3 ) << a[ j ];
34
35 cout << "


Effects of passing array element by value:"
36 << "

a[3] before modifyElement: " << a[ 3 ] << endl;
37
38 modifyElement( a[ 3 ] ); // pass array element a[ 3 ] by value
39 cout << "a[3] after modifyElement: " << a[ 3 ] << endl;
40
41 return 0; // indicates successful termination
42 } // end main
43
44 // in function modifyArray, "b" points to the original array "a" in memory
45 void modifyArray( int b[], int sizeOfArray ) 
46 { 
47  // multiply each array element by 2 
48  for ( int k = 0; k < sizeOfArray; k++ ) 
49  b[ k ] *= 2; 
50 } // end function modifyArray 
51
52 // in function modifyElement, "e" is a local copy of 
53 // array element a[ 3 ] passed from main 
54 void modifyElement( int e ) 
55 { 
56  // multiply parameter by 2 
57  cout << "Value of element in modifyElement: " << ( e *= 2 ) << endl;
58 } // end function modifyElement 
 
 Effects of passing entire array by reference:

 The values of the original array are:
 0 1 2 3 4
 The values of the modified array are:
 0 2 4 6 8


 Effects of passing array element by value:

 a[3] before modifyElement: 6
 Value of element in modifyElement: 12
 a[3] after modifyElement: 6
 

There may be situations in your programs in which a function should not be allowed to modify array elements. C++ provides the type qualifier const that can be used to prevent modification of array values in the caller by code in a called function. When a function specifies an array parameter that is preceded by the const qualifier, the elements of the array become constant in the function body, and any attempt to modify an element of the array in the function body results in a compilation error. This enables the programmer to prevent accidental modification of array elements in the function's body.

Figure 7.15 demonstrates the const qualifier. Function tryToModifyArray (lines 2126) is defined with parameter const int b[], which specifies that array b is constant and cannot be modified. Each of the three attempts by the function to modify array b's elements (lines 2325) results in a compilation error. The Microsoft Visual C++.NET compiler, for example, produces the error "l-value specifies const object." [Note: The C++ standard defines an "object" as any "region of storage," thus including variables or array elements of fundamental data types as well as instances of classes (what we've been calling objects).] This message indicates that using a const object (e.g., b[ 0 ]) as an lvalue is an erroryou cannot assign a new value to a const object by placing it on the left of an assignment operator. Note that compiler error messages vary between compilers (as shown in Fig. 7.15). The const qualifier will be discussed again in Chapter 10.


Figure 7.15. const type qualifier applied to an array parameter.

(This item is displayed on page 350 in the print version)

 1 // Fig. 7.15: fig07_15.cpp
 2 // Demonstrating the const type qualifier.
 3 #include 
 4 using std::cout;
 5 using std::endl;
 6
 7 void tryToModifyArray( const int [] ); // function prototype
 8
 9 int main()
10 {
11 int a[] = { 10, 20, 30 };
12
13 tryToModifyArray( a );
14 cout << a[ 0 ] << ' ' << a[ 1 ] << ' ' << a[ 2 ] << '
';
15
16 return 0; // indicates successful termination
17 } // end main
18
19 // In function tryToModifyArray, "b" cannot be used
20 // to modify the original array "a" in main. 
21 void tryToModifyArray( const int b[] ) 
22 { 
23  b[ 0 ] /= 2; // error 
24  b[ 1 ] /= 2; // error 
25  b[ 2 ] /= 2; // error 
26 } // end function tryToModifyArray 
 

Borland C++ command-line compiler error message:

 Error E2024 fig07_15.cpp 23: Cannot modify a const object
 in function tryToModifyArray(const int * const)
 Error E2024 fig07_15.cpp 24: Cannot modify a const object
 in function tryToModifyArray(const int * const)
 Error E2024 fig07_15.cpp 25: Cannot modify a const object
 in function tryToModifyArray(const int * const)
 
 

Microsoft Visual C++ .NET compiler error message:

 C:cpphtp5_examplesch07fig07_15.cpp(23) : error C2166: l-value specifies
 const object
 C:cpphtp5_examplesch07fig07_15.cpp(24) : error C2166: l-value specifies
 const object
 C:cpphtp5_examplesch07fig07_15.cpp(25) : error C2166: l-value specifies
 const object
 
 

GNU C++ compiler error message:

 fig07_15.cpp:23: error: assignment of read-only location
 fig07_15.cpp:24: error: assignment of read-only location
 fig07_15.cpp:25: error: assignment of read-only location
 

Common Programming Error 7.11

Forgetting that arrays in the caller are passed by reference, and hence can be modified in called functions, may result in logic errors.

Software Engineering Observation 7.4

Applying the const type qualifier to an array parameter in a function definition to prevent the original array from being modified in the function body is another example of the principle of least privilege. Functions should not be given the capability to modify an array unless it is absolutely necessary.


Introduction to Computers, the Internet and World Wide Web

Introduction to C++ Programming

Introduction to Classes and Objects

Control Statements: Part 1

Control Statements: Part 2

Functions and an Introduction to Recursion

Arrays and Vectors

Pointers and Pointer-Based Strings

Classes: A Deeper Look, Part 1

Classes: A Deeper Look, Part 2

Operator Overloading; String and Array Objects

Object-Oriented Programming: Inheritance

Object-Oriented Programming: Polymorphism

Templates

Stream Input/Output

Exception Handling

File Processing

Class string and String Stream Processing

Web Programming

Searching and Sorting

Data Structures

Bits, Characters, C-Strings and structs

Standard Template Library (STL)

Other Topics

Appendix A. Operator Precedence and Associativity Chart

Appendix B. ASCII Character Set

Appendix C. Fundamental Types

Appendix D. Number Systems

Appendix E. C Legacy Code Topics

Appendix F. Preprocessor

Appendix G. ATM Case Study Code

Appendix H. UML 2: Additional Diagram Types

Appendix I. C++ Internet and Web Resources

Appendix J. Introduction to XHTML

Appendix K. XHTML Special Characters

Appendix L. Using the Visual Studio .NET Debugger

Appendix M. Using the GNU C++ Debugger

Bibliography



C++ How to Program
C++ How to Program (5th Edition)
ISBN: 0131857576
EAN: 2147483647
Year: 2004
Pages: 627

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net