C语言中指针数组做函数形参,数组指针做形参

一、C语言中的数组指针与指针数组

首先我们需要了解什么是数组指针以及什么是指针数组,如下图:

int *p[5];             //指针数组
int (*p)[5];           //数组指针

那么两个之间有什么区别呢:

数组指针的意思即为通过指针引用数组,p先和*结合,说明了p是一个指针变量,指向一个大小为5的数组。所以,int (*p)[5]即为一个数组指针。int *p[5]则是一个大小为5且存放整型指针的数组。

1、指针数组

对于语句“intp1[5]”,因为“[]”的优先级要比“”要高,所以 p1 先与“[]”结合,构成一个数组的定义,数组名为
p1,而“int*”修饰的是数组的内容,即数组的每个元素。也就是说,该数组包含 5 个指向 int 类型数据的指针,如图 1
所示,因此,它是一个指针数组。

C语言中指针数组做函数形参,数组指针做形参_第1张图片

2、数组指针

对于语句“int(p2)[5]”,“()”的优先级比“[]”高,“”号和 p2 构成一个指针的定义,指针变量名为 p2,而 int
修饰的是数组的内容,即数组的每个元素。也就是说,p2 是一个指针,它指向一个包含 5 个 int 类型数据的数组,如图 2
所示。很显然,它是一个数组指针,数组在这里并没有名字,是个匿名数组。

C语言中指针数组做函数形参,数组指针做形参_第2张图片

总结

那么也可以理解为数组指针是指向数组的指针,其中数组中存放的还是指针,那么这就可以可以和二级指针的概念进行转换,以下通过实例来对两者进行对比。以下着重讲述指针数组,

int arr[5]={1,2,3,4,5};
int (*p1)[5] = &arr;
/*下面是错误的*/
int (*p2)[5] = arr;

在上面的示例代码中,&arr 是指整个数组的首地址,而 arr 是指数组首元素的首地址,虽然所表示的意义不同,但二者之间的值却是相同的。那么问题出来了,既然值是相同的,为什么语句“int(*p1)[5]=&arr”是正确的,而语句“int(*p2)[5]=arr”却在有些编译器下运行时会提示错误信息呢(如在 Microsoft Visual Studio 2010 中提示的错误信息为“a value of type"int*"cannot be used to initialize an entity of type"int(*)[5]"”)?

其实原因很简单,在 C 语言中,赋值符号“=”号两边的数据类型必须是相同的,如果不同,则需要显示或隐式类型转换。在这里,p1 和 p2 都是数组指针,指向的是整个数组。p1 这个定义的“=”号两边的数据类型完全一致,而 p2 这个定义的“=”号两边的数据类型就不一致了(左边的类型是指向整个数组的指针,而右边的数据类型是指向单个字符的指针),因此会提示错误信息。

二、指针数组作为形参传递

typedef struct {
    int a;
    int b;
}test;

void func1(test* tmp[]){
    printf("func1:%d\n", ((test*)tmp + 0)->a);
    printf("func1 ((test*)tmp)[0].c:%d\n", ((test*)tmp)[0].b);
    
    printf("func1:%d\n", ((test*)tmp + 1)->a);
    printf("func1 ((test*)tmp)[1].c:%d\n", ((test*)tmp)[1].b);
}
    
void func2(test* tmp){
    printf("func2 ((test*)tmp + 0)->a:%d\n", ((test*)tmp + 0)->a);
    printf("func2 tmp[0].b:%d\n", tmp[0].b);
    printf("func2 ((test*)tmp + 1)->a:%d\n", ((test*)tmp + 1)->a);
    printf("func2 tmp[1].b:%d\n", tmp[1].b);
}

int main(int argc, char const *argv[])
{
    test aa[2];
    aa[0].a = 1;
    aa[0].b = 2;
    
    aa[1].a = 3;
    aa[1].b = 4;
    
    func1((test**)aa);
    printf("------------------------\n");
    func2((test*)aa);
    return 0;
}

结果:

func1:1
func1 ((test*)tmp)[0].c:2
func1:3
func1 ((test*)tmp)[1].c:4
------------------------
func2 ((test*)tmp + 0)->a:1
func2 tmp[0].b:2
func2 ((test*)tmp + 1)->a:3
func2 tmp[1].b:4

其实除了上述两种传参的方式之外还可以使用值传递的方式;

void func_3(test aa[]) 

这种方式不再进行详解。

三、数组指针作为形参传递

typedef struct {
    int a;
    int b;
}test;

void func3(test (*tmp)[]){
    printf("func1:%d\n", (*tmp)->a);
    printf("func1:%d\n", (*tmp)->b);
    printf("func1:%d\n", (*tmp)[0].a);
    printf("func1:%d\n", (*tmp)[0].b);

    printf("=========================\n");
    
    printf("func1:%d\n", ((test*)tmp)[0].a);
    printf("func1:%d\n", ((test*)tmp)[0].b);
    printf("func1:%d\n", ((test*)tmp+1)->a);
    printf("func1:%d\n", ((test*)tmp+1)->b);

    printf("=========================\n");

    printf("func3:%d\n", (*tmp + 1)->a);
    printf("func3:%d\n", (*tmp + 1)->b);
    printf("func1:%d\n", (*tmp)[1].a);
    printf("func1:%d\n", (*tmp)[1].b);
}

int main(int argc, char const *argv[])
{
    test aa[2];
    aa[0].a = 1;
    aa[0].b = 2;
    
    aa[1].a = 3;
    aa[1].b = 4;
    
    func3(&aa);
    return 0;
}


结果:

func1:1
func1:2
func1:1
func1:2
=========================
func1:1
func1:2
func1:3
func1:4
=========================
func3:3
func3:4
func1:3
func1:4

你可能感兴趣的:(C语言,c语言,开发语言)