[original] on the correlation between two-dimensional array of pointers and multi-level pointers

This article is only published in the blog Park, and other websites are stolen. Please consciously support the genuine version: https://www.cnblogs.com/jisuanjizhishizatan/p/15732439.html

preface

Recently, I saw someone write a wrong code in the school, as follows:

void dfs(int graph[][],int used[][],int x,int y);

Such code is bound to make mistakes (from the perspective of grammar). Feel it and write down this content.
I haven't written about dry goods for a long time recently. I'll write more dry goods this time.

1. Pointer as function parameter

1.1. One dimensional array (review)

#include<bits/stdc++.h>
using namespace std;
void f(int a[]){
	cout<<sizeof(a)<<endl;
}
int main(){
	int a[]={1,2,3};
	cout<<sizeof(a)<<endl;
	f(a);
}

Outputs 12.8 on 64 bit machines and 12.4 on 32-bit machines
Through this experiment, we come to the conclusion that: * when a one-dimensional array is passed as a parameter of a function, it will be used as a pointer to the first element of the array.

1.2. Pointer to array

Our experiment in the previous section is only a pointer to the first element of the array, not a pointer to the array.
The real pointer to the array is this:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int a[]={1,2,3};
	int (*p)[3]=&a;
	cout<<sizeof(*p)<<endl;
}

The output is 12, that is, three sizeof(int).
As you can see, * p is the array a. if you use the drawing method of memory diagram, it should be as follows:

So, some people will ask, what's the difference between this and the pointer to the first element of the array? Of course, there is a big difference.
We assume that the pointer to the first element of the array is Q, then when p++;q++; When,

The array will look like the above, that is, q increases sizeof(int), and p increases sizeof(a), that is, three int bits.

1.3. Addressing mode of two-dimensional array

In our human understanding, array a[2][3] is arranged as follows:

But in the understanding of the machine, it is actually arranged as follows:

Let's do an experiment:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int a[2][3]={1,2,3,4,5,6};
	for(int i=0;i<2;i++){
		for(int j=0;j<3;j++){
			printf("%p ",&a[i][j]);
		}
		printf("\n");
	}
}

The results are as follows:

00000000006ffe00 00000000006ffe04 00000000006ffe08
00000000006ffe0c 00000000006ffe10 00000000006ffe14

Yes, it's arranged linearly.
a[i][j], as we are familiar with, is actually addressed as follows:

*(*(a+i)+j)

We see the following figure:

At this time, a[0] is the pointer to the array, which points to the array {1,2,3}, and a[1] points to the array {4,5,6}.
Then, a[0]+1 is the pointer to element 2, and then dereference * to get the value 2
Namely: * (a[0]+1)=a[0][1]
It can be generalized to the expansion of the above two-dimensional array: a[i][j]=*(*(a+i)+j)

1.4. Two dimensional array as function parameters

Following the experiment in Section 1.1, we are doing a similar experiment.

#include<bits/stdc++.h>
using namespace std;
int f(int a[2][3]){
	cout<<sizeof(a)<<endl;
}
int main(){
	int a[2][3]={1,2,3,4,5,6};
	cout<<sizeof(a)<<endl;
	f(a);
}

Output: 24 8 (64 bit) or 24 4 (32 bit)
Therefore, we find that when a two-dimensional array is used as a function parameter, it also passes a pointer.
It is worth noting here that for the same model, we generally need to test the 32-bit and 64 bit output results at the same time in order to make a better judgment. If an output value has twice the relationship between 32-bit and 64 bit, it is generally a pointer.
For some debugging environments (such as DEV C + +), 32-bit and 64 bit debugging modes can be selected,

Our conclusion is that the two-dimensional array is passed as the parameter of the function, and the pointer to the array is passed.
That is, this function is synonymous with the following functions.

int f(int (*a)[3]){
	for(int i=0;i<2;i++){
		for(int j=0;j<3;j++){
			cout<<a[i][j]<<" ";
		}
		cout<<endl;
	}
}

Back to the question at the beginning of the chapter, why can't used [] [] be written in the declaration of function parameters?
The answer is very simple. a[i][j] is equivalent to * (* (a+i)+j), where,
According to the principle of pointer operation, * (a+i), i*sizeof(a[0]) is actually added instead of i
In this way, because the size of a[0] is unknown in the function parameter, the width of the array must be specified manually

Otherwise, the array cannot be interpreted due to different widths
If the declaration is written as (* a)[4], the interpretation of two-dimensional arrays will be completely different.

Will be explained to do so.
If the width of the array is specified, the size of a[0] is also determined, and the addressing can be carried out smoothly.

2. Secondary pointer

2.1. concept

#include<bits/stdc++.h>
using namespace std;
int main(){
	int a=10;
	int *p=&a;
	int **pp=&p;
	printf("%d %d %d",a,*p,**pp);
}

Output: 10

The * * pp with two asterisks is the secondary pointer.
Type comparison list:

2.2. application

In function parameters, if you want to modify the value, you must use a pointer (or reference).
Then, in the function parameters, if you want to modify the value of the pointer, you need the pointer of the pointer, that is, multi-level pointer.

#include<bits/stdc++.h>
using namespace std;
void f1(char *s){
	s="abcd";
}
void f2(char **s){
	*s="abcd";
}
int main(){
	char *s="first";
	f1(s);puts(s);
	f2(&s);puts(s);
}

Note that secondary pointers and two-dimensional arrays, and pointers to arrays are three completely different things.
End.

Added by fazlionline on Sun, 02 Jan 2022 06:12:51 +0200