数组和指针的传参问题
数组传参
一维数组传参
#include<stdio.h>
void test(int arr[])//ok?
{
}
void test(int arr[10])//ok?
{
}
void test(int *arr)//ok?
{
}
void test2(int *arr[20])//ok?
{
}
void test2(int **arr)//ok?
{
}
int main()
{
int arr[10]={0};
int *arr2[20]={0};
test(arr);
test(arr2);
}
(1)可以,数组取下标操作符内的数字可省略、可为任何数。(2)可以(3)可以,数组传参时降维为指针,形参就算以数组形式表示,编译器也会认为其为一个指针。(4)可以,存放整形指针的数组,形参以同样形式接受是正确的。(5)可以,将arr2[20]先暂时认为一个数组,传参后形参为指针,这个指针的类型为int *型。
二维数组传参
int main()
void test(int arr[3][5])//ok?
{
}
void test(int arr[][])//ok?
{
}
void test(int arr[][5])//ok?
{
}
void test(int *arr)//ok?
{
}
void test(int (*arr)[5])//ok?
{
}
void test(int **arr)//ok?
{
}
{
int arr[3][5]={0};
test(arr);
}
(1)可以,实参以二维数组形式传参,形参以二维数组接受是可以的。(2)错误,二维数组传参时形参只能省略离数组名最近的下标操作符内的数字,其余均不可省略,均需要正确输入数字;因为数组可以不知道有多少行,但必须知道每一行有多少元素,这样更方便运算。(3)可以(4)错误,理论上将二维数组看为一个整体,形参为一个指针,但这样容易与一维数组的传参混淆,不建议使用,认为错误。(5)正确。形参为存放指针的数组,一行元素有5个,此种写法为最规范的写法,建议使用。(6)错误。实参为数组,形参为二级指针,二级指针可接受二级指针、一级指针的地址、指针数组、一维数组的地址。
多维数组传参
#include<stdio.h>
#include<stdlib.h>
void test(int (*arr)[2][2])
{
}
int main()
{
int arr[3][2][2] = { 0 };
test(arr);
system("pause");
return 0;
}
指针传参
一级指针传参
#include<stdio.h>
void print(int *p,int sz)
{
int i=0;
for(i=0;i<sz;i++)
{
printf("%d\n",*(p+i));
}
}
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9};
int *p=arr;
int sz=sizeof(arr)/sizeof(arr[0]);
print(p,sz);
//或
//print(arr,sz);
return 0;
}
一级指针可接受一维数组、指针、&a。
二级指针传参
#include<stdio.h>
void test(int **ptr)
{
printf("num=%d\n",**ptr);
}
int main()
{
int n=10;
int *p=&n;
int **pp=&p;
test(pp);
test(&p);
return 0;
}
二级指针可接受一维数组地址、指针数组、二级指针、一级指针地址。
传值调用和传址调用
传值调用:除了数组,其他数据实参均以直接拷贝,以传值形式调用。
传址调用:数组传参时不可直接拷贝,需降维为指针;但数据也可以进行传址调用,只要在它前面加上取地址操作符即可。
为什么要创建临时变量?
(1)提高整个程序的安全性(若出现数据丢失,main函数中还有)
(2)提高可使用性(若某一函数有问题,其他正常)
总结:
(1)数组传参时均会发生降维现象。
(2)数组降维为指针,所有数组均为一维数组。
(3)认识上所有数组均为一维数组,数组传参时会降维为指向其内部元素类型的指针。
(4)在32位平台下,所有指针类型传参均消耗4个字节,形成指针临时变量。