//指针数组:存放指针
char* arr[5];
//数组指针:指向数组的指针
int ar[10]={0};
int (*p) [10]=&arr;
int arr [ 5 ];//arr是一个整型数组,每个元素是int类型的,有5个元素int * parr1 [ 10 ];//parr1是一个数组,每个元素是int*类型的,有10个元素int ( * parr2 )[ 10 ];//parr2是一个指向数组的指针,指向的数组有10个元素,每个元素的类型是intint ( * parr3 [ 10 ])[ 5 ];//parr3是一个数组,数组有10个元素,每个元素的类型是int(*)[5]//parr3是存放数组指针的数组
四、 数组参数、指针参数
如果把数组或者指针传给函数,函数的参数该如何设计呢?
1.一维数组传参
//形参写成数组的形式
void test(int arr[10])
{
}
void test(int arr[])//形参部分数组大小可以省略
{
}
void test(int arr[100])//不建议,但是没错
{
}
//形参写成指针的形式
void test(int *p)
{
}
//test2
void test2(int* arr[20])
{
}
void test2(int* arr[])
{
}
void test2(int**p)//二级指针
{
}
int main()
{
int arr[10] = {0};
int *arr2[20] = {0};
test(arr);
test2(arr2);
}
2.二维数组传参
//形参写成数组的形式
void test(int arr[3][5])
{
}
void test(int arr[][])//×,行可以省略,列不能省略
{
}
void test(int arr[][5])
{
}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//形参写成指针的形式
void test(int *arr)//×
{
}
void test(int* arr[5])//×
{
}
void test(int (*arr)[5])//√ arr+1跳一行
{
}
void test(int **arr)//×,二级指针存放一级指针的地址
{
}
void test(int (*arr)[3][5])
{
//*arr是第一行的地址
}
int main()
{
int arr[3][5] = {0};
test(arr);//这里数组名是首元素地址,二维数组的首元素是第一行,地址是第一行的地址
test1(&arr);//传的是整个二维数组的地址
}
3.一级指针传参
void test1(int *p)
{
}
//test1函数能接收什么参数?
//int a=10;int* p=&a;int arr[10];
//可以传&a,p,arr
void tset(int *p, int sz)
{
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,10};
int *p = arr;
int sz = sizeof(arr)/sizeof(arr[0]);
test(p, sz);//一级指针p,传给函数
}
4.二级指针传参
void test(int** ptr)
{
printf("num = %d\n", **ptr);
}
int main()
{
int n = 10;
int*p = &n;
int **pp = &p;//pp是一个二级指针
test(pp);
test(&p);
int*ar[4];//指针数组
test(ar);//指针数组的数组名是首元素的地址是指针的地址,是二级指针
}
五、函数指针
函数指针:指向函数的指针
int Add(int x,int y)
{
return x+y;
}
int test(char* str)
{
}
int main()
{
int arr[10];
int (*p) [10]=&arr;//p是一个数组指针变量
printf("%p\n",&Add);//函数地址
printf("%p\n",Add);//函数地址
int (*pf)(int,int)=Add;//pf是函数指针变量,pf等于Add
int ret=(*pf)(2,3);*是摆设可以没有,加*时()不能去掉
int ret1=pf(2,3);
printf("%d\n",ret);//5
printf("%d\n",ret1);//5
int (*pt)(char*)=test;
}
//代码1
( *(void (*) () )0 ) ();
//void (*) () 是函数指针类型
// (void (*) () )0 对0进行强制类型转换
//1.首先把0强制类型转换为函数指针类型,
//这就意味着0地址处放一个返回类型是void无参的一个函数
//2.调用0地址处的这个函数
// 代码 2void ( * signal ( int , void ( * ) ( int ) ) ) ( int );//函数声明typedef void(* pf_t) (int);//给函数指针类型 void ( * ) ( int )重新起名叫pf_tpf_t signal(int,pf_t); // void ( * signal ( int , void ( * ) ( int ) ) ) ( int )的简化//signal是函数名//signal函数的第一个参数的类型是int,第二个参数的类型是 void ( * ) ( int ) 是函数指针类型//signal函数的返回类型是 void ( * ) ( int )是函数指针
六、函数指针数组
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a*b;
}
int div(int a, int b)
{
return a / b;
}
int main()
{
//指针数组
char* arr[5];//字符指针数组
int* arr2[4];//整型指针数组
//函数指针
int (*pf1)(int,int)=add;
int (*pf2)(int,int)=sub;
int (*pf3)(int,int)=mul;
int (*pf4)(int,int)=div;
//函数指针类型int(*)(int,int)
//函数指针数组
int (*pf[4])(int,int)={add,sub,mul,div);
for(int i=0;i<4;i++)
{
int ret=pf[i](8,2);
printf("%d ",ret);//10 6 16 4
}
}
实现一个计算器
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a*b;
}
int div(int a, int b)
{
return a / b;
}
void menu()
{
printf("1.add\n2.sub\n3.mul\n4.div\n0.exit\n");
}
int main()
{
int input=0,x=0,y=0,ret=0;
int(*p[5])(int x, int y)={ 0, add, sub, mul, div};//转移表
do
{
menu();
printf("请选择\n");
scanf("%d",&input);
if(input==0)
{
printf("退出计算器\n");
}
else if(input<=4&&input>=1)
{
printf( "输入操作数:\n");
scanf( "%d %d", &x, &y);
ret = (*p[input])(x, y);
printf("%d\n",ret);
}
else printf("选择错误\n);
}while(input);
}