As we know, the expression x [i] to access the ith element of vector x can be equivalently written using pointer notation as * (x+i) . Thus, the expression a [i] [j] to access the ijth element of matrix a can be equivalently written as * (*(a+i) +j). Observe that this expression is obtained by applying twice the construct used for a vector. The address of a [i][j] is thus given as * (a+i) +j. These results are summarized below.
a[i][j] = *(*(a+i)+j) &a[i][j] = *(a+i)+j
To understand these expressions. Consider again the matrix declared as int a [3] [4]. Due to the left-to-right associativity of the [] operators, this is equivalent to (a [3] ) [4], i. e., a is an array having three elements each of which is also an array having four elements, as depicted in Fig.
The array name is a pointer to the first row and the expression a+i is a pointer to the ith row. Dereferencing it as * (a+i) gives us the element contained in the ith row, which is an array having 4 elements. As an array (name) is actually a pointer to its beginning, * (a+i) is obviously a pointer to the first element of this array. Thus, the expression * (a+ i) +j gives a pointer to thejth element in this matrix (in the ith row). Thus, dereferencing it as * (* (a+i)+j) gives the jth element, i. e., a [i] [j].
Note that the expression a+i which is a pointer to the ith row and * (a+i) which is a pointer to the first element in the ith row, both point to the same memory location, i. e., they have same value. However, they are different as the first one is a row pointer which, when incremented, advances to the next row, whereas the second one is an element pointer which, when incremented, advances to the next element in that row.
If the element being accessed is in the first row and/or first column, we can rewrite the element access expression as shown below.
**a Element in first row, first column **(a+i) Element in ith row, first column *(*a+j) Element in first row, jth column
Example of Matrix manipulation using matrix name as a pointer
a) Print a matrix
for (i = 0; i < m; i++) { for (j = 0; j < n; j++) printf("%2d ", *(*(a+i)+j) ); /* a[i][j] */ printf("\n"); }
This program segment uses nested for loops to print a matrix (or its portion) of size m x n. Observe that instead of the subscript notation (a [i] [j] ), the array elements are printed using the equivalent pointer expression * (* (a+i) +j).
b) Read a matrix
for (i = 0; i < m; i++) { for (j = 0; j < n; j++) scanf("%d", *(a+i)+j ); /* &a[i] [j] */ }
This code segment reads a matrix of size m x n from the keyboard. Note that the expression & a [i] [j] is replaced by its pointer equivalent, * (a+i) +j.
Accessing Matrix Elements Using Another Pointer Variable
As we have just seen, the expression to access a matrix element using its name as a pointer is quite involved. We can improve code readability and efficiency by using a separate pointer variable that steps through the matrix.
There are two possible approaches to implement this. In first approach, we need to initialize a pointer to the beginning of a row to be processed and increment this pointer after each element is processed. This approach is particularly suitable for dynamic arrays in which each row is allocated a separate block of memory. In another approach, we can take advantage of the fact that the entire matrix is allocated a contiguous block of memory. We can thus initialize a pointer to the beginning of a matrix and increment it each time an element is processed.
Example of Process a matrix using a separate pointer variable
The function imat_prrnt2 given below prints an integer matrix using the first approach mentioned above. It uses a pointer variable pa to point to the element to be printed. For each row being printed, this pointer is initialized to the first element of that row using the expression * (a+i).The pointer is incremented after each element is printed using the expression *pa++.
The function mat_print3 given below uses the second approach in which the pointer variable pa is first initialized to point to the beginning of the matrix (i. e., element a [o][o]) using the expression *a. Then a nested for loop is used to print the matrix. Note how the pointer is incremented after each element is printed using expression *pa++.
void imat_print3(int a[] [4], int m, int n) { int i, j; int *pa = *a; /* init int pointer to point to a[0] [0] */ for (i = 0; i < m; i++) { for (j = 0; j < n; j++) printf("%2d ", *pa++); /*access elem & incr pointer*/ printf("\n"); } }
Finally, note that we can initialize pointer pa using typecast as shown below.
int *pa = (int *) a; /* init int pointer to point to a[0] [0] */
Passing a Matrix to a Function Using a Pointer
As we know, we need not specify the number of rows when a matrix is passed to a function. Thus, the mat_func function given below specifies that a matrix having unknown number of rows, each having four elements, will be passed as the actual argument.
void mat func(int a[] [4], int m, int n);
We can pass this matrix using equivalent pointer declaration as int (*a) [4]. Here, the parentheses surrounding *a are essential. We read this declaration as follows: a is a pointer to an array having four elements of type int. Since a is a pointer, we can pass an array having several elements, each of which is a four-element array, i.e., a matrix of size n x 4. Thus, the declaration of mat_func function given above can be equivalently rewritten as
void mat_func (int (*a) [4], int m, int n);
Note that within the function, we can access the elements of this matrix using the usual subscript notation. The imat_print4 function to print a matrix of size n x 4 is given below.
void imat_print4(int (*a) [4], int m, int n) { int i, j; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) printf("%2d ", a[i] [j]);/* access elem using subscript*/ printf("\n"); } }