Two-dimensional arrays and secondary pointers in function parameters
Preface:
_Two-dimensional arrays are passed through a second-order pointer in a template function given by leetcode, which also gives an array of Row rows and Col columns. a[i][j] is often used directly in the function to traverse each element of the two-dimensional array.A segment error occurs when a [i][j] traverses the array in a function when the two-dimensional array actually declared at the time of writing code is in the stack.To explore the reasons, this paper summarizes the array pointer, the pointer array, and the two-dimensional array and secondary pointer in the function parameters.
1. Array pointers and arrays of pointers
[]Operator precedence over* therefore[]First with p Combination int *p[10]; // Pointer array An int * pointer array of size 10 int (*p)[10]; // Array pointer An int pointer to an array of size 10
2. Array names and de-references in two-dimensional arrays
for example:2-D Array a[3][3],Where: a a First address Type is: int (*)[3] &a a First address Type is: int [3][3] &a[0] a First address Type is: int (*)[3] &a[0][0] a First address Type is: int *
_The above type declaration can be verified by the following code, which also indicates that a[3][3] is equivalent to a[9] = {1,2,3,4,5,6,7,8,9} and that a[2][1] is equivalent to a[1][4], where array crossovers or segment errors do not occur, i.e., a[i][j] = *(*(a+i)+j) = *(*(int*) a + i).
/* Array names and de-references in two-dimensional arrays */ #include <stdio.h> int main(){ int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9} }; printf("a in stack\n"); printf("a:%p\ta+1:%p\n",a,a+1); printf("&a:%p\t&a+1:%p\n",&a,&a+1); printf("&a[0]:%p\t&a[0]+1:%p\n",&a[0],&a[0]+1); printf("&a[0][0]:%p\t&a[0][0]+1:%p\n",&a[0][0],&a[0][0]+1); }
_The above code two-dimensional arrays are declared on the stack, whereas when using malloc to dynamically declare two-dimensional arrays, it is often necessary to declare a second-level pointer (int **a) before storing the first address of each row of subarrays, where a[i][j] = *(*(a + i) + j) must be established and not necessarily equal to *((int *)a + i*Col + j), because the address space dynamically allocated by each row of subarrays is not necessarily continuous.
#include <stdio.h> #include <stdlib.h> int func(int **array, int m, int n) { printf("array in heap\n"); printf("array[i][j]\t*((int *)array + i * 3 + j)\n"); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { printf("%d\t\t", array[i][j]); printf("%d", *((int *)array + i * n + j)); printf("\n"); } } printf("\n"); return 0; } int main() { int **array = (int **)malloc(sizeof(int *) * 3); for (int i = 0; i < 3; ++i) { array[i] = (int *)malloc(sizeof(int) * 3); for (int j = 0; j < 3; ++j) { array[i][j] = i * 3 + j + 1; } } func(array,3,3); return 0; }
3. Two-dimensional arrays and secondary pointers in function parameters
_First of all, it is important to note that there is no difference between a two-dimensional array and a secondary pointer, and then when passing a two-dimensional array to a function, you need to note whether it is dynamically allocated on or in the stack.
-
Heap Allocation
Heap allocation for two-dimensional arrays has been mentioned in the previous section. Function parameters are usually passed directly by a second-order pointer. Arrays can be traversed directly by a[i][j] in a function, but not by *((int *)a + i *Col + j). -
Stack Assignment
If two-dimensional arrays are allocated on the stack, this is a more complex situation, and the general pattern is as follows:
// 1.int (*)[Col] parameter type void fun(int a[Row][Col]); void fun(int a[][Col]); void fun(int (*a)[Col]);
_In the above three ways, the array can be traversed either directly through a[i][j] in a function or through *((int *)a + i *Col + j).In addition, two-dimensional arrays allocated in the stack can also be passed through secondary pointers, but in this way arrays cannot be traversed directly by a[i][j], but only by *((int *)a + i *Col + j).
// 2.int ** Parameter type void fun(int **a);
_The actual type of the array name a is int (*)[Col]. When using the array name a as a function argument, the type is forced to convert to int **, the de-reference *(*(a + i) + j) of a[i][j], which is actually equivalent to **((int *)a + i + j), and accessing an address with a value of a[i + j] causes a segment error.To solve this problem, you can convert a secondary pointer (int **) to an (int (*)[Col]) pointer before traversal, or store the first address of each row's subarray in a pointer array before arguments are passed in.
1.int (*)ptr[Col] = (int (*)[Col])a; 2.int *ptr[Row] = {0}; for (int i = 0; i < Row; ++i) { ptr[i] = a[i]; }