四 数组参数 指针参数
4.1 一维数组传参
数组传参的时候,形参写成数组形式是可以的,例如:arr[10],,,,传参后写成int arr[] 是可以的,int arr[10],也是可以的,下标写错也是可以的。实际上,我们传递的是数组名,数组名也就是首元素地址 用指针来接收的话,也是可以的,要注意类型。
代码展示:
#include <stdio.h>
void test(int arr[])//ok? ok
{}
void test(int arr[10])//ok? ok
{}
void test(int* arr)//ok? ok
{}
void test2(int* arr[20])//ok? ok
{}
void test2(int** arr)//ok? ok
{}
int main()
{
int arr[10] = { 0 };
int* arr2[20] = { 0 };
test(arr);
test2(arr2);
}
4.2 二维数组传参
void test(int arr[3][5])//ok? ok
{}
void test(int arr[][])//ok? not 行可以省略,列不可以省略
{}
void test(int arr[][5])//ok? ok 指向一行5个,类型为int的指针
{}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
//二维数组传参,传的是数组首元素地址,指的是二维数组第一行的地址,而不是第一行第一个元素的地址
void test(int* arr)//ok? not
{}
void test(int* arr[5])//ok? not 这是一个数组,不是一个指针
{}
void test(int(*arr)[5])//ok? ok 是一个指向 int [5]类型的指针
{}
void test(int** arr)//ok? not
{}
int main()
{
int arr[3][5] = { 0 };
test(arr);
}
4.3 一维指针传参
#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]);
//一级指针p,传给函数
print(p, sz);
return 0;
}
这种方法,不常见,最好别用。
一级指针重要的内容是,当函数的参数是一级指针的时候,可以接收什么样的参数。
代码展示:
1. #include <stdio.h> 2. void test(int* p) 3. { 4. 5. } 6. int main() 7. { 8. int a = 10; 9. int* ptr = &a; 10. int arr[10] = { 0 }; 11. test(&a); 12. test(ptr); 13. test(arr); 14. return 0; 15. }
4.4 二维指针传参
二级指针重要的内容是,当函数的参数是二级指针的时候,可以接收什么样的参数。
1. #include <stdio.h> 2. void test(int** ptr) 3. { 4. printf("num = %d\n", **ptr); 5. } 6. int main() 7. { 8. int n = 10; 9. int* p = &n; 10. int** pp = &p; 11. test(pp); 12. test(&p); 13. int* arr[10]; 14. test(arr); 15. return 0; 16. }
五 函数指针
函数指针,指向函数的指针。
函数是有地址的,地址是 函数名或者&函数名,解引用时,pf和*pf都可以。
代码展示:
1. #include <stdio.h> 2. void Add(int x, int y) 3. { 4. return x + y; 5. } 6. int main() 7. { 8. printf("%p\n", &Add); 9. printf("%p\n", Add);//这两行和数组指针不能类比,函数没有首元素地址。 10. int (*pf)(int, int) = &Add;//这一行可以和数组指针类比一下。pf是一个函数指针 &Add写成Add也是可以的,因为&Add和Add一样。 11. int sum = (*pf)(2, 3);//用指针调用这个函数 12. int sum2 = (pf)(3, 5);//所以*可要可不要 13. int (*pf1)(int, int) = Add;//用Add的时候 &Add和Add是一样的 14. int sum1 = (pf1)(3, 4); 15. printf("%d\n", sum); 16. return 0; 17. }
&函数名和函数名 得到的都是函数的地址。
无返回类型用void (*pf)(int, int)
&Add相当于Add,所以,*可要可不要。
1. (*(void (*)())0)(); 2. //void(*)()无参数的函数指针,()0 把0强制类型转换,*{()0} 解引用这个函数,(*)(),调用这个函数 3. //0本来是int类型,然后强制转换成函数指针,然后此时,0就是一个函数的地址,式子就可以看成(*0)()解引用一个函数地址并且调用。 4. //就是一次函数调用
上个代码是函数调用
1. void (*signal(int, void(*)(int)))(int); 2. //signal是一个函数,signal后面括号里面不是参数,说明是一个函数声明, 3. //signal(int, void(*)(int),仅仅看这个,是一个缺少函数返回类型的函数声明,那么剩下的就是函数声明的返回类型 void(*)(int), 4. 5. typedef void (* pfun_t)(int); 6. pfun_t signal(int, pfun_t);//简化
上个代码是一个函数声明
六 函数指针数组
函数指针数组,存放函数指针的数组,每一个元素都是函数指针类型。
1. #include <stdio.h> 2. int Add(int a, int b) 3. { 4. return a + b; 5. } 6. int Sub(int a, int b) 7. { 8. return a - b; 9. } 10. int Mul(int a, int b) 11. { 12. return a * b; 13. } 14. int Div(int a, int b) 15. { 16. return a / b; 17. } 18. int main() 19. { 20. int (*pf1)(int, int) = Add; 21. int (*pf2)(int, int) = Sub; 22. int (*pf3)(int, int) = Mul; 23. int (*pf4)(int, int) = Div;//四个函数指针 24. int (*arr[4])(int, int) = { Add, Sub, Mul, Div};//数组;*,函数指针,(int, int)函数指针数组 arr[4] 数组,数组里面的每一个元素是 函数指针类型 25. int i = 0; 26. for (i = 0; i < 4; i++) 27. { 28. printf("%d\n", arr[i](4, 2)); 29. } 30. return 0; 31. }
应用:计算机
1. #include <stdio.h> 2. int Add(int a, int b) 3. { 4. return a + b; 5. } 6. int Sub(int a, int b) 7. { 8. return a - b; 9. } 10. int Mul(int a, int b) 11. { 12. return a * b; 13. } 14. int Div(int a, int b) 15. { 16. return a / b; 17. } 18. void menu() 19. { 20. printf("******1.Add 2.Sub*******\n"); 21. printf("******3.Mul 4.Div*******\n"); 22. printf("******0.exit *******\n"); 23. printf("**********************8****\n"); 24. } 25. int main() 26. { 27. int input = 0; 28. int a = 0; 29. int b = 0; 30. int (*arr[5])(int, int) = { 0, Add, Sub, Mul, Div }; 31. do 32. { 33. menu(); 34. printf("请选择:"); 35. scanf("%d", &input); 36. if (input >= 1 && input <= 4) 37. { 38. printf("输入两个操作数:->"); 39. scanf("%d %d", &a, &b); 40. printf("%d\n", arr[input](a, b)); 41. } 42. else if (input == 0) 43. { 44. printf("退出程序"); 45. } 46. else 47. { 48. printf("选择错误\n"); 49. break; 50. } 51. } while (input); 52. return 0; 53. }