指针的进阶(三)

简介: 指针的进阶(三)

四 数组参数 指针参数

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. }


相关文章
|
4月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
4月前
|
机器学习/深度学习 搜索推荐 算法
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
|
4月前
|
C语言
指针进阶(回调函数)(C语言)
指针进阶(回调函数)(C语言)
|
4月前
|
存储 C语言 C++
指针进阶(函数指针)(C语言)
指针进阶(函数指针)(C语言)
|
4月前
|
编译器 C语言
指针进阶(数组指针 )(C语言)
指针进阶(数组指针 )(C语言)
|
4月前
|
搜索推荐
指针进阶(2)
指针进阶(2)
42 4
|
4月前
指针进阶(3)
指针进阶(3)
36 1
|
4月前
|
C++
指针进阶(1)
指针进阶(1)
40 1
|
4月前
|
存储 安全 编译器
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
40 2
|
4月前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
43 0