函数和指针

Posted hhzc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数和指针相关的知识,希望对你有一定的参考价值。

1、指针与函数的返回值

 

技术分享图片
 1 #define A 0
 2 int funcA(int a, int b)
 3 {
 4     return a + b;
 5 }
 6 
 7 /*把指针作为函数的返回值*/
 8 int * funcB(int a, int b)
 9 {
10     static int c = A;
11     c = a + b;
12     return &c;
13 }
14 /*通过函数进行内存的申请*/
15 /*
16 * 参数:要申请的内存大小
17 * 返回值:申请好的内存的首地址 
18 * 这是一种不好的方式
19 */
20 int * funcC(int size)
21 {
22     return (int *)malloc(size);
23 }
24 /*通过函数进行内存的申请*/
25 /*
26 * 参数:要申请的内存能够保存多少个int变量
27 * 返回值:申请好的内存的首地址
28 */
29 int * funcD(int sum)
30 {
31     return (int*)malloc(sizeof(int)* sum);
32 }
33 
34 /*函数返回值测试*/
35 int main001(int argc, char **argv)
36 {
37     int *p_int, temp;
38     p_int = funcB(2, 5);
39     printf("%d \n", *p_int );
40 
41     temp = *funcB(4, 8); /*这样写是不推荐的形式*/
42 
43     /* &temp = funcB(5, 7); */ /*这样是错误的*/
44 
45 
46     system("pause");
47     return 0;
48 }
49 
50 int main(int argc, char **argv)
51 {
52     int* p_int;
53 
54     /*想想看,前面声明的哪个函数原型合理?*/
55     p_int = funcC(20);
56     for (int i = 0; i < 20 / sizeof(int); i++)
57     {
58         p_int[i] = i; 
59     }
60     p_int = funcD(5);
61     for (int i = 0; i < 5; i++)
62     {
63         p_int[i] = i;
64     }
65     system("pause");
66     return 0;
67 }
指针与函数的返回值

 

2、指针和函数的参数

 

函数传参的两种方式:传值和传址

 

如果是传值,在被调函数内部不能改变主调函数变量的值。

 

如果是传址,在被调函数内部可以通过地址来操作外部的变量。

 

3、函数指针

 

指向函数的指针

 

函数名称本身就是一个函数指针。

 

比如:int (*p_func)(int)

 

第一个int是返回值,p_func函数指针的名称,(*p_func) 考虑到匹配优先级问题,要加括号,第二个int是函数指针对应函数的参数。

 

函数指针的意义,从内存中找到需要执行的代码对应的首地址, 

 

注意,函数指针的类型要与其指向的函数原型相吻合

 

 函数申请与释放内存

 

1、 malloc

 

2、 realloc

 

3、 calloc  申请内存后帮助我们初始化内存的内容,其余和malloc功能完全一样

 

4、 free 释放内存

应用:回调函数

 

实现回调函数机制的流程:

 

A、 首先需要一个主调函数,他至少要有一个参数是函数指针。

 

B、 实现回调函数,回调函数的 函数原型必须要和主调函数中函数指针的类型相匹配

 

C、 根据业务需要或具体情况决定该传入哪一个函数指针

 

技术分享图片
 1 int clock(int time)
 2 {
 3     if (time == 6)
 4     {
 5         printf("零零零零。。。。\n");
 6         return 1;
 7     }
 8     else
 9     {
10         printf("我不出声,只是看着你。。。\n");
11         return 0;
12     }
13 
14 }
15 /*父母的行为*/
16 int parent(int time)
17 {
18     if (time >= 6)
19     {
20         printf("太阳晒屁股了,快起床!\n");
21         return 1;
22     }
23     else
24     {
25         printf("我是不叫醒呢,不叫醒呢,还是不叫醒呢。。。\n");
26         return 0;
27     }
28 
29 }
30 /************************************************************************/
31 /* 定义主调函数                                                                     */
32 /************************************************************************/
33 /*触发唤醒*/
34 int weakup(int(*p_func)(int), int time)
35 {
36     if (!p_func(time)) /*没有到时间*/
37     {
38         printf("zzzzzzzzzzzzzzzzz\n");
39         return 0;
40     }
41     else
42     {
43         if (time == 6)
44         {
45             printf("再睡一会儿。。。\n");
46             return 0;
47         }
48         else
49         {
50             printf("好吧,你赢了,我起床。。。");
51             return 1;
52         }
53     }
54 
55 }
56 
57 /*处理主框架,决定主调函数使用哪个函数指针*/
58 int main(int argc, char** argv)
59 {
60     for (int i = 0; i <= 24; i++)
61     {
62         printf("当前时间:%d\n", i);
63         if (weakup(clock, i))
64         {
65             break;
66         }
67 
68         if (weakup(parent, i))
69         {
70             break;
71         }
72     }
73     system("pause");
74     return 0;
75 }
示例

 

 
 

多重指针

二级指针

指向指针的指针,它本身也是一个指针,类型是指向的那个指针类型的指针类型。

 1 int main()
 2 {
 3    /* int a = 100;
 4     int *b = &a;
 5     int **c = &b;
 6     */
 7     int a;
 8     int *b;
 9     int **c;
10     a = 100;
11    // *b = a;错误写法 b是一个地址,*b是从一个地址中取出的常量。
12     b = &a;
13     c = &b;
14 
15     printf("a=%d\tb=%d\tc=%d\n",a,*b,**c);
16     printf("a=%p\tb=%p\tc=%p\n",&a,b,c);
17     printf("a=%p\tb=%p\tc=%p\n",&a,&b,&c);
18 
19     return 0;
20 }

 

二级指针的用途:

二级指针用作函数的输出参数,可以返回函数内申请的内存地址。

 

技术分享图片
 1 /*二级指针用途*/
 2 
 3 /*一级指针做内存申请实验*/
 4 int funcA(int * p_int)
 5 {
 6     p_int = (int *)malloc(sizeof(int)* 10);
 7     return 0;
 8 }
 9 
10 /*二级指针做内存申请实验*/
11 int funcB(int ** pp_int)
12 {
13     *pp_int = (int*)malloc(sizeof(int)* 10);
14     printf("*pp_int = %p\n", *pp_int);
15     return 0;
16 
17 }
18 
19 int main(int argc, char** argv)
20 {
21     int *p_int1 = NULL;
22     int *p_int2 = NULL;
23     printf("p_int1 = %p, p_int2 = %p\n", p_int1, p_int2);
24     funcA(p_int1);
25     funcB(&p_int2);
26     printf("p_int1 = %p, p_int2 = %p\n", p_int1, p_int2);
27 
28     system("pause");
29     return 0;
30 }
二级指针的用途

p_int1 = 0x7ffc45c421e0, p_int2 = 0x7ffc45c421e4
*p_int = 0x55aabf873670
*pp_int = 0x55aabf8736a0
p_int1 = 0x7ffc45c421e0, p_int2 = 0x55aabf8736a0

二级指针生成二维数组

前置知识点:

指针数组:数组的内容是指针类型。

例:定义一个整型指针的数组  int* arr_int[10];

指针类型数组元素都是指针类型的,当我们把指针类型的元素全都指向有意义的内存空间时,就可以使用二级指针来生成二维数组了

 

技术分享图片
 1 int main(int argc, char** argv)
 2 {
 3     /*首先定义一个二级指针变量*/
 4     int ** pp_arr = NULL;
 5 
 6     /*先生成数组的第一维*/
 7     pp_arr = (int**)malloc(sizeof(int*) * 4 );
 8 
 9     /*通过循环生称第二维*/
10     for (int i = 0; i < 4; i++)
11     {
12         //元素类型是一级指针
13         pp_arr[i] = (int*)malloc( sizeof(int)* 10);  /*第二维数组长度为10*/
14 
15     }
16     /*到此为止,使用二级指针生称了二维数组*/
17 
18     for (int i = 0; i < 4; i++)
19     {
20         for (int j = 0; j < 10; j++)
21         {
22             pp_arr[i][j] = rand();
23         }
24     }
25 
26     /*打印出数组内容*/
27     for (int i = 0; i < 4; i++)
28     {
29         for (int j = 0; j < 10; j++)
30         {
31             printf("[%d]", pp_arr[i][j]);
32         }
33         printf("\n");
34     }
35     system("pause");
36     return 0;
37 }
二级指针生成二维数组

 




以上是关于函数和指针的主要内容,如果未能解决你的问题,请参考以下文章

使用 std::thread 函数 C++11 将指针作为参数传递

片段中的 EditText 上的空指针异常 [重复]

活动到片段通信:当我尝试从活动更新片段中的文本视图时,出现空指针异常

空指针异常 - 片段活动

片段中的 Listview 适配器给出空指针异常

rootView上的Android片段空指针异常[关闭]