二维数组传参
二维数组传参传的也是首元素的地址,不是数组。
arr[0][0] a | arr[0][1] b |
arr[1][0] c | arr[1][1] d |
arr[2][0] e | arr[2][1] f |
char arr[3][2] = {a, b, c, d, e, f };
上面这个数组左边是下标,右边是储存的元素。
二维数组传参是怎么进行的呢?
void Print(char *p[2])
{
for(int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
printf("%c", *(*(p+i)+j));
}
}
}
int main()
{
char arr[3][2]={a,b,c,d,e,f};
Print(arr)//建立一个Print函数,把这个二维字符数组传参,打印这个二维数组
return 0;
}
如图,可以把二维数组arr[3][2]看作一个一维数组的数组,这个数组里有三个元素,每一个元素都是一个一维数组,那么第一个一维数组就是arr[0],第二个是arr[1],第三个是arr[2]。arr[0]是一个一维数组,这个数组有两个元素,第一个是a,第二个是b.
二维数组传参传的是首元素的地址,在这个例子中,首元素的地址----arr[0]----的地址,arr[0]是一个一维数组,它存入的是arr[0]中首元素----arr[0][0]---的地址。二维数组的首元素是一个数组,那么它的地址就是一个数组指针,所以也要用数组指针类型接收。char *p[2] 表示接收的数组有两个元素(arr[0]中有两个元素), 指向的对象是char型的字符。* 表示p是一个指针。
p是一个数组指针,p+1跳过的就是一个数组。*(*(p+0)+0)访问arr[0][0],*(p+0)表示第一行的地址解引用,解引用后就是二维数组的第一个元素arr[0],arr[0]既是二维数组的第一个元素,也是第一行数组的数组名,作为数组名,它又是首元素的地址。所以*p+1,就是指针从arr[0][0]指向了arr[0][1],解引用,就是*(*p+1)得到了arr[0][1]的值b。
二维数组通过指针访问, 对指针解引用也就是 *(*(p+行变量)+列变量) 得到具体的值。
p+行变量 得到二维数组的某行的首元素地址,对地址解引用得到该行元素的名字(arr[1]/arr[2]/arr[3]),由于它们是数组,所以数组名也是它们的首元素的地址。 *(p+行变量)+列变量,通过再加列变量,指针移动找到这一行相对应的具体位置。此时还是指针,所以还要解引用才能得到最终的结果!
函数指针变量
int (*p) (int,int) = Add ;
这是函数指针变量的声明,int 表示函数Add返回的是一个int型的值。*p表示这个函数是一个指针。(int ,int)表示Add传的两个参数是int型。
函数名也是函数的地址,所以声明时,既可以加取地址符号,也可以不加。
int Add (int x , int y)
{
return x+y;
}
int main( )
{
int (*p)(int, int) = Add;
int i = 0;
printf("%d",(*p)(2, 3));
printf("%d",p(2,3));
return 0;
}
通过指针访问函数,函数名就是函数的地址,这里声明以后,指针也相当于函数名,可以不用解引用,直接传参数就可以。
函数指针数组
int ( *p[3]) (int , int ) = { Add, Sub , Mul ,Div , Mod };
以上是函数指针数组的声明,p[3]结合表明这是个数组, int * () 表示是一个函数指针。数组里面都是函数指针。
转移表
如下图所示,将函数放在一个数组里面,组成一个函数指针数组,然后通过指针来访问它们。
这是函数指针访问函数,与函数指针数组的结合。形成这个集合加减乘除的简单计算器。