Detailed explanation of two-dimensional arrays and array pointers

Two-dimensional array

In-depth understanding of two-dimensional arrays

  • First define a two-dimensional array

    int a[2][3]={
          
          {
          
          1,2,3},{
          
          4,5,6}};
    #or int a[2][2]={1,2,3,4};
    

    New understanding: We can think of it like this, a can be regarded as a one-dimensional array, containing 2 elements, each element is exactly an element containing 3 integers, the value of the name a becomes a pointer to an array containing 3 integers. A pointer to an array of type elements (you should know that if you have learned array pointers, they are the same thing, I will explain array pointers later)

  • Then start to discuss the relationship between two-dimensional arrays and array names

    a represents the first address of the entire array, and a[0] represents the first address of the first row. The two are numerically the same, but have different meanings (or different types). The array name a is for the entire array. Array , a[0] is for the first row.

#打印 a a[0] 的值和 a[0][0] 的地址
cout << a << endl;#0x7ffffffee120
cout << a[0] << endl;#0x7ffffffee120	
cout << &a[0][0] << endl;#0x7ffffffee120

So a、a[0]the value and a[0][0]the address of the three expressions point to an address.

  • Then look at each line

    cout << a[0] << endl;#0x7ffffffee120
    cout << a[1] << endl;#0x7ffffffee12c
    

    The output result is the first address of each line, and the difference between the two addresses is 12 bytes, which is the size of three ints.

  • Below we deduce elements at other locations by summing these two addresses a[0].&a[0][0]

    # 由a[0]推出其他,这里以第1行第1列为例
    cout << a[0+1]+1 << endl;			#0x7ffffffee130
    cout << *(a[0+1]+1) << endl;		#5
    cout << a[0]+4 << endl;				#0x7ffffffee130
    cout << *(a[0]+4) << endl;			#5
    
    # 由&a[0][0]推出其他, 这里以第1行第1列为例
    cout << &a[0][0]+4<< endl;		#0x7ffffffee130
    cout << *(&a[0][0]+4) << endl;	#5
    

    The first two lines obtain the first address of other lines by adding the index of a[0], and then add the offset to obtain the element address, and dereference to obtain the value of the address.

    The next two lines directly calculate the offset of a[0] to obtain the element address, and dereference to obtain the value of the element address. The last two lines are the same as in the case of adding the offset directly.

  • get other elements by array name

    a
    

    a is the name of the array, its type is "pointer to an array containing three integer elements", and it defaults to the first row.

    a+1
    

    Now it points to the second line. It can be understood that when an int* pointer points to an int in an array, ++ points to the latter int. Similarly, the array pointer here points to an array, so + + He is about to point to the next array.

    *(a+1

    If we get int type data after int* dereference, what about array pointer? In fact, we dereference a pointer to an array and get an array .

    *(a+1== a[1]
    

    *(a+1) is the array name in the second line. If you think this expression is strange, then a[1] has the same meaning as him.

    We now get the second row of this two-dimensional array. The second row is actually a one-dimensional array, so maybe all our processing can be done in a one-dimensional array.

    *(a+1+ 1
    

    Let him point to the second element in this array.

    **(a+1+ 1

    The last step is to get the desired value.

    Let's take a look at some questions about taking addresses

    printf("%d\n",sizeof(a+1));//8//第二行的地址(指针的大小)
    printf("%d\n",sizeof(&a[0]+1));//8
    printf("%d\n",sizeof(*(&a[0]+1)));//12
    

    1. a is an array pointer. After adding one, it points to the next line. He is still a pointer, and sizeof is the size of the pointer.

    2. Get the address of a[0]? a[0] is the name of a one-dimensional array, that is, a pointer, and the result of taking the address again is a second-level pointer. Before, we dereferenced the array pointer to get the array name, but this time it is just the opposite, so &arr[0] you can understand that we now get an array pointer, and +1 to the array pointer is to let it point to the second row, in sizeof is the size of the pointer. (So ​​array pointers are also called secondary pointers)

    3. Dereference the array pointer to get the name of the array in the second row, and sizeof is the size of the second row.

  • A final test

    int a[2][3] = {
          
          0};
    printf("%d\n",sizeof(a));//24//输出这个二维数组的大小
    printf("%d\n",sizeof(a[0][0]));//4//第一个元素的大小(int)
    printf("%d\n",sizeof(a[0]));//12//第一行的数组的大小
    printf("%d\n",sizeof(a[0]+1));//8//第一行第二个元素的地址(指针的大小)
    printf("%d\n",sizeof(*(a[0]+1)));//4//第一行第二个元素的大小
    printf("%d\n",sizeof(a+1));//8//第二行的地址(指针的大小)
    printf("%d\n",sizeof(*(a+1)));//12//第二行的大小
    printf("%d\n",sizeof(&a[0]+1));//8//第二行的地址(指针的大小)
    printf("%d\n",sizeof(*(&a[0]+1)));//12//第二行的大小
    printf("%d\n",sizeof(*a));//12//第一行的大小
    printf("%d\n",sizeof(a[2]));//12//虽然越界了但是sizeof只是一个关键字他不关心这块空间是否真的存在
    

    array pointer

In order to better understand the relationship between pointers and two-dimensional arrays, let's first define a pointer variable p that points to a:int (*p)[3] = a;

The * in parentheses indicates that p is a pointer to an array of type int[3], which is exactly the type of every one-dimensional array contained in a. [ ] has a higher priority than *, and ( ) must be added. If it is written as int *p[4], it should be understood as int *(p[4]), p becomes an array of pointers, and Not a 2D array pointer.

When adding (subtracting) a pointer, its forward (backward) step is related to the data type it points to. The data type pointed to by p is int [3], then p+1 advances 3 × 4 = 12 words section, p-1 goes back 12 bytes, which is exactly the length of each one-dimensional array contained in array a. That is, p+1 will make the pointer point to the next row of the two-dimensional array, and p-1 will make the pointer point to the previous row of the array.

There is an essential difference between an array of pointers and a pointer to a two-dimensional array: an array of pointers is an array, but each element holds a pointer. A two-dimensional array pointer is a pointer that points to a two-dimensional array, taking a above as an example, it occupies 8 bytes of memory.

Equivalence relation:

a+i == p+i
a[i] == p[i] == *(a+i) == *(p+i)
a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)

  • small exercise

    int main()
    {
          
          
    	int arr[][3] = {
          
           1, 2, 3, 4, 5, 6 };
    	int(*p)[3];
    	p = arr;
    	cout << p[0][0] << " " << *(p[0] + 1) << " " << (*p)[2] << endl;
    	return 0;
    }
    

    1. p[0][0]Access the first element of the first row according to the subscript, and output 1.
    2. *(p[0] + 1)This makes the first row pointer point to the second element and then dereferences it, outputting 2.
    3. (*p)[2]Equivalent to *(*p+2), first dereference the array pointer to get the first row of the array name, then add it to the third position for dereference, and output 3.

Two-dimensional array of parameters

  • Passing parameters using the traditional way of defining a 2D array

    If the array name is used as a parameter of the function, the array parameter will automatically degenerate into a pointer when compiling. Therefore, although the following two ways of writing are different, they are the same after compiling, and the array will degenerate into an array pointer.

#include <iostream>
using namespace std;
/*以下两种写法本质上是一样的*/
int func1(int (*arr)[4]) {
    
    
	arr[0][2] = 20;
	return 0;
} 
int func2(int arr[][4]) {
    
    
	arr[0][2] = 30;
	return 0;
}
int main(){
    
    
	int array[3][4] = {
    
    1,2,3,4,5,6,7,8,9,10,11,12}; 
	func2(array);
	cout << array[0][2] << endl;//fun1: 20 or fun2: 30
	return 0;
}
  • Use dynamic allocation of memory to apply for space, you can use ** to pass parameters

    Which method is used to define which method is used to pass parameters.

#include <iostream>
using namespace std;
int func1(int **arr) {
    
    
	cout << arr[0][1]<< endl;
	arr[0][2] = 20;    
	return 0;
}
int main(){
    
    
    int rows=3 ;
    int cols=4 ;
    int **arr = new int*[rows];//先使一个二级指针指向数组指针的地址
    for(int i = 0 ; i < rows ;++i )
    {
    
    
        arr[i] = new int [cols]();//为一级指针分配地址
    }
    arr[0][1]=100;
    func1(arr);
    cout << arr[0][2]<< endl;;
    //释放空间
    for(int i = 0; i < rows ;++i)
    {
    
    
        delete [] arr[i];//先释放二维数组中每个元素指向的数组
        arr[i] = NULL;
    }
    delete [] arr;//在释放该数组指针;
    arr = NULL;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324134565&siteId=291194637
Recommended