8.6. Arrays as Arguments of FunctionsWhen the name of an array appears as a function argument, the compiler implicitly converts it into a pointer to the array's first element. Accordingly, the corresponding parameter of the function is always a pointer to the same object type as the type of the array elements. You can declare the parameter either in array form or in pointer form: type name[ ] or type *name. The strcat( ) function defined in Example 8-1 illustrates the pointer notation. For more details and examples, see the section "Arrays as Function Parameters" in Chapter 7. Here, however, we'll take a closer look at the case of multidimensional arrays. When you pass a multidimensional array as a function argument, the function receives a pointer to an array type. Because this array type is the type of the elements of the outermost array dimension, it must be a complete type. For this reason, you must specify all dimensions of the array elements in the corresponding function parameter declaration. For example, the type of a matrix parameter is a pointer to a "row" array, and the length of the rows (i.e., the number of "columns") must be included in the declaration. More specifically, if NCOLS is the number of columns, then the parameter for a matrix of float elements can be declared as follows: #define NCOLS 10 // The number of columns. /* ... */ void somefunction( float (*pMat)[NCOLS] ); // A pointer to a row array. This declaration is equivalent to the following: void somefunction( float pMat[ ][NCOLS] ); The parentheses in the parameter declaration float (*pMat)[NCOLS] are necessary in order to declare a pointer to an array of float. Without them, float *pMat[NCOLS] would declare the identifier pMat as an array whose elements have the type float*, or pointer to float. See the section "Complex Declarators" in Chapter 11. In C99, parameter declarations can contain variable-length arrays. Thus in a declaration of a pointer to a matrix, the number of columns need not be constant, but can be another parameter of the function. For example, you can declare a function as follows: void someVLAfunction( int ncols, float pMat[ ][ncols] ); Example 7-5 shows a function that uses a variable-length matrix as a parameter. If you use multidimensional arrays in your programs, it is a good idea to define a type name for the (n-1)-dimensional elements of an n-dimensional array. Such typedef names can make your programs more readable and your arrays easier to handle. For example, the following typedef statement defines a type for the row arrays of a matrix of float elements (see also the section "typedef Declarations" in Chapter 11): typedef float ROW_t[NCOLS]; // A type for the "row" arrays. Example 8-2 illustrates the use of an array type name such as ROW_t. The function printRow( ) provides formatted output of a row array. The function printMatrix( ) prints all the rows in the matrix. Example 8-2. Functions printRow( ) and printMatrix( )// Print one "row" array. void printRow( const ROW_t pRow ) { for ( int c = 0; c < NCOLS; ++c ) printf( "%6.2f", pRow[c] ); putchar( '\n' ); } // Print the whole matrix. void printMatrix( const ROW_t *pMat, int nRows ) { for ( int r = 0; r < nRows; ++r ) printRow( pMat[r] ); // Print each row. } The parameters pRow and pMat are declared as pointers to const arrays because the functions do not modify the matrix. Because the number of rows is variable, it is passed to the function printMatrix( ) as a second argument. The following code fragment defines and initializes an array of rows with type ROW_t, and then calls the function printMatrix( ): ROW_t mat[ ] = { { 0.0F, 0.1F }, { 1.0F, 1.1F, 1.2F }, { 2.0F, 2.1F, 2.2F, 2.3F } }; int nRows = sizeof(mat) / sizeof(ROW_t); printMatrix( mat, nRows ); |