Mastering Algorithms With C - Kyle Loudon [12]
The conversion of a multidimensional array to a pointer is analogous to converting a one-dimensional array. However, we also must remember that in C, multi-dimensional arrays are stored in row-major order. This means that subscripts to the right vary more rapidly than those to the left. To access the element at row i and column j in a two-dimensional array, we use the expression:
a[i][j]
C treats a in this expression as a pointer that points to the element at row 0, column in a. The expression as a whole is equivalent to:
*(*(a + i) + j)
Figure 2.3. Using pointer arithmetic to reference an array of (a) integers and (b) characters
Pointers as Parameters to Functions
Pointers are an essential part of calling functions in C. Most importantly, they are used to support a type of parameter passing called call-by-reference. In call-by-reference parameter passing , when a function changes a parameter passed to it, the change persists after the function returns. Contrast this with call-by-value parameter passing, in which changes to parameters persist only within the function itself. Pointers are also an efficient means of passing large amounts of data in and out of functions, whether we plan to modify the data or not. This method is efficient because only a pointer is passed instead of a complete copy of the data. This technique is used in many of the examples in this book.
Call-by-Reference Parameter Passing
Formally, C supports only call-by-value parameter passing. In call-by-value parameter passing , private copies of a function's calling parameters are made for the function to use as it executes. However, we can simulate call-by-reference parameter passing by passing pointers to parameters instead of passing the parameters themselves. Using this approach, a function gets a private copy of a pointer to each parameter in the caller's environment.
To understand how this works, first consider swap1, which illustrates an incorrect implementation of a function to swap two integers using call-by-value parameter passing without pointers. Figure 2.4 illustrates why this does not work. The function swap2 corrects the problem by using pointers to simulate call-by-reference parameter passing. Figure 2.5 illustrates how using pointers makes swapping proceed correctly.
Incorrect Swap
Correct Swap
void swap1(int x, int y) {
int tmp;
tmp = x; x = y; y = tmp;
return;
}
void swap2(int *x, int *y) {
int tmp;
tmp = *x; *x = *y; *y = tmp;
return;
}
Figure 2.4. An illustration of swap1, which uses call-by-value parameter passing and fails to swap two integers in the caller's environment
Figure 2.5. An illustration of swap2, which simulates call-by-reference parameter passing and successfully swaps two integers in the caller's environment
One of the nice things about C and call-by-reference parameter passing is that the language gives us complete control over exactly how parameter passing is performed. One disadvantage, however, is that this control can be cumbersome since we often end up having to dereference call-by-reference parameters numerous times in functions.
Another use of pointers in function calls occurs when we pass arrays to functions. Recalling that C treats all array names transparently as unmodifiable pointers, passing an array of objects of type T in a function is equivalent to passing a pointer to an object of type T. Thus, we can use the two approaches interchangeably. For example, function