精华内容
下载资源
问答
  • 函数三要素: 名称、参数、返回值。C语言中的函数有自己特定的类型。 c语言中通过typedef为函数类型重命名: typedef int f(int, int); // f 为函数类型 typedef void p(int); // p 为函数类型 这一点和数组一样,...

    函数指针做函数参数(回调函数)

    函数参数除了是普通变量,还可以是函数指针变量,也就是可以实现回调函数。

    所谓回调,就是模块A要通过模块B的某个函数b()完成一定的功能,但是函数b()自己无法实现全部功能,需要反过头来调用模块A中的某个函数a()来完成,这个a()就是回调函数。

    回调函数概念

    回调函数是程序中一种常用的函数调用方式。其特点是可以在下层软件模块(宏观上的被调用者)中,调用来自上层的软件模块(宏观上的调用者)中的函数,这和通常的调用顺序是相反的。

    程序的调用方式软件模块的关系,从总体上看,有上层软件模块和下层软件模块之分。

    一般有三种调用方式

    1. 简单的同步调用上调下直接返回
    2. 带有回调的调用双向调用
    3. 异步调用一般基于消息或事件类似MFC的机制

    带有回调的调用方式是一种双向调用模式,在这种方式中,下层模块的函数在被调用的时候,将会调用上层模块的某个函数,回调上层模块的函数至少有两个作用,一是监视下层模块函数的运行状态,二是干预下层模块函数的运行

    在C语言中回调函数的基础是函数类型的指针。

    回调函数的作用

    回调函数的作用:回调函数的表现形式是一个某种类型的函数指针,这个函数由上层的软件模块实现,将这个函数指针通过某种方式传递给下层的软件模块,由下层的软件模块在某个时刻调用这个函数。

    函数指针的本质是一个函地址,在32位的系统中,本质是一个32位无符号整数。

    函数指针由上层模块传递到下层模块的传递方式是可以通过函数的参数传递,也可以使用结构体的成员进行传递。

    回调函数调用时刻

    调用回调函数的时刻一般有两种:

    • 一种是在上层模块调用下层模块的函数中,直接调用回调函数:
    • 另一种是使用注册的方式,在某个事件发生的时候下层模块调用回调函数。

    回调函数的语法:

    1.简单的函数类型为:无参数、无返回值的函数。

    简单的回调函数的格式是这种形式。其类型的定义如下所示:

    typedef void*T_SIMPLE_CALLBACK)(void);
    

    注:回调函数可以是任意类型的函数指针,简单的形式是无任何参数,也没有返回值得函数指针

    2.完全形式的回调函数

    完全形式的回调函数可以按照如下方式实现,它包含两个无符号整数的参数,返回值也是无符号的整数。其类型的定义如下所示:

    typedef unsigned int*T_FULL_CALLBACK)(unsigned int para1,unsigned int para2);
    

    具体例如这样:

    //形参为普通变量
    void fun( int x ){}
    //形参为函数指针变量
    void fun( int(*p)(int a) ){}
    

    函数指针变量常见的用途之一:是把指针作为参数传递到其他函数,指向函数的指针也可以作为参数,以实现函数地址的传递。

    注:

    1.典型的回调函数包含两个整数型参数和整数返回值,第一个参数由下层定义,第二个参数由上层定义返回值是上层经过回调反馈给下层的
    2.事实上,这种回调机制在一个系统的各个层次软件协同处理的时候很常用。例如,下层模块表示一个GUI系统,具有绘制界面的功能,上层将模块将回调函数的指针传递给下层,当界面产生“事件”的时候,调用回调函数执行上层软件模块所定制的行为。

    代码案例:模拟计算器

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    int plus(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 division(int a, int b)
    {
    	return a / b;
    }
    
    //函数指针 做函数的参数 --- 回调函数
    void Calculator(int(*myCalculate)(int, int), int a, int b)
    {
    	int ret = myCalculate(a, b); //dowork中不确定用户选择的内容,由后期来指定运算规则
    	printf("ret = %d\n", ret);
    }
    
    void test01()
    {
    	printf("请输入操作符\n");
    	printf("1、+ \n");
    	printf("2、- \n");
    	printf("3、* \n");
    	printf("4、/ \n");
    
    	int select = -1;
    	scanf("%d", &select);
    
    	int num1 = 0;
    	printf("请输入第一个操作数:\n");
    	scanf("%d", &num1);
    
    	int num2 = 0;
    	printf("请输入第二个操作数:\n");
    	scanf("%d", &num2);
    
    	switch (select)
    	{
    	case  1:
    		Calculator(plus, num1, num2);
    		break;
    	case  2:
    		Calculator(sub, num1, num2);
    		break;
    	case 3:
    		Calculator(mul, num1, num2);
    		break;
    	case 4:
    		Calculator(division, num1, num2);
    		break;
    	default:
    		break;
    	}
    
    }
    
    int main()
    {
    	while (1)
    	{
    		test01();
    	}
    	return 0;
    }
    

    运行结果为:
    在这里插入图片描述

    展开全文
  • 编号指针函数参数内存分配方式(级别+堆栈)主调函数实参被调函数形参备注011级指针(输入)堆分配使用一般应用禁用栈分配使用常用Int showbuf(char *p);int showArray(int *array, int iNum)021级指针(输出)栈使用...

    编号

    指针函数参数

    内存分配方式(级别+堆栈)

    主调函数

    实参

    被调函数

    形参

    备注

    01

    1级指针

    (做输入)

    分配

    使用

    一般应用禁用

    分配

    使用

    常用

    Int showbuf(char *p);

    int showArray(int *array, int iNum)

    02

    1级指针

    (做输出)

    使用

    结果传出

    常用

    int geLen(char *pFileName, int *pfileLen);

    03

    2级指针

    (做输入)

    分配

    使用

    一般应用禁用

    分配

    使用

    常用

    int main(int arc ,char *arg[]);指针数组

    int shouMatrix(int [3][4], int iLine);二维字符串数组

    04

    2级指针

    (做输出)

    使用

    分配

    常用,但不建议用,转化成02

    int getData(char **data, int *dataLen);

    Int getData_Free(void *data);

    Int getData_Free(void **data); //避免野指针

    05

    3级指针

    (做输出)

    使用

    分配

    不常用

    int getFileAllLine(char ***content, int *pLine);

    int getFileAllLine_Free(char ***content, int *pLine);

    指针做函数参数,问题的实质不是指针,而是看内存块,内存块是1维、2维。

    如果基础类int变量,不需要用指针;

    若内存块是1维、2维。

    1、二级指针三种内存模型的建立:堆区、栈区、常量区

    30662effea246ee1a91ba7237c2d090b.png

    2、二级指三种内存模型字符串排序举例:

    1、二级指针第一种内存模型:常量区

    int sortArray07(char**pstr, int num)

    {

    int i = 0, j = 0;

    int ret = 0;

    char*tmp = NULL;     //交换的是指针变量,因此定义一个临时指针变量

    if (pstr == NULL)

    {

    ret = -1;

    printf("sortArray07() param err:%d\n", ret);

    return ret;

    }

    for (i = 0; i < num; i++)

    {

    for (j = i + 1; j < num; j++)

    {

    if (strcmp(pstr[i], pstr[j])>0)

    {

    tmp = pstr[i];

    pstr[i] = pstr[j];

    pstr[j] = tmp;

    }

    }

    }

    return ret;

    }

    void main07()

    {

    char*myArray[] = { "bbbb", "111111", "aaaaa", "ccccc" };//字符串在常量区,四个指针变量存放了该地址

    printf("排序前\n");

    printArray07(myArray, 4);

    sortArray07(myArray, 4);

    printf("排序后\n");

    printArray07(myArray, 4);

    system("pause");

    }

    2、二级指针第二种内存模型:栈区

    int sortArray08(char (*pstr)[10], int num)

    {

    int i = 0, j = 0;

    char tmp[1024] = { 0 };    //交换的是只存空间的内容,而不是指针变量,因此定义一个临时缓冲区充当交换空间

    for (i = 0; i < num; i++)

    {

    for (j = i + 1; j < num; j++)

    {

    if (strcmp(pstr[i], pstr[j])>0)

    {

    strcpy(tmp, pstr[i]);

    strcpy(pstr[i], pstr[j]);

    strcpy(pstr[j], tmp);

    }

    }

    }

    return 0;

    }

    void main08()

    {

    char myArray[][10] = { "bbbb", "111111", "aaaaa", "ccccc" };//字符串在栈区,从常量区拷贝到栈区

    printf("二级指针第二种内存模型排序前\n");

    printArray08(myArray, 4);

    sortArray08(myArray, 4);

    printf("二级指针第二种内存模型排序后\n");

    printArray08(myArray, 4);

    system("pause");

    }

    3、二级指针第三种内存模型:堆区

    //交换的是指针变量所指向空间的内容、类似栈区空间内容的交换

    int sortArray091(char**pstr, int num)

    {

    int i = 0, j = 0;

    char tmp[1024] = { 0 };

    for (i = 0; i < num; i++)

    {

    for (j = i + 1; j < num; j++)

    {

    if (strcmp(pstr[i], pstr[j])>0)

    {

    strcpy(tmp ,pstr[i]);

    strcpy(pstr[i], pstr[j]);

    strcpy(pstr[j], tmp);

    }

    }

    }

    return 0;

    }

    //交换的是指针变量,和常量区交换是一样的

    int sortArray092(char**pstr, int num)

    {

    int i = 0, j = 0;

    char*tmp = NULL;      //交换的是指针变量

    for (i = 0; i < num; i++)

    {

    for (j = i + 1; j < num; j++)

    {

    if (strcmp(pstr[i], pstr[j])>0)

    {

    tmp = pstr[i];

    pstr[i] = pstr[j];

    pstr[j] = tmp;

    }

    }

    }

    return 0;

    }

    char**getMem( int num)

    {

    char**myArray = (char**)malloc(100 * sizeof(char*));

    for (int i = 0; i < num; i++)

    {

    myArray[i] = (char*)malloc(12 * sizeof(char));

    }

    return myArray;

    }

    void main()

    {

    char**myArray = NULL;

    myArray = getMem(4);

    if (myArray == NULL)

    {

    printf("malloc err\n");

    return;

    }

    strcpy(myArray[0], "bbbb");

    strcpy(myArray[1], "111111");

    strcpy(myArray[2], "aaaaa");

    strcpy(myArray[3], "ccccc");

    printf("二级指针第三种内存模型排序前\n");

    printArray09(myArray, 4);

    //交换指针变量

    //sortArray091(myArray, 4);

    //交换指针变量所指向的空间

    sortArray092(myArray, 4);

    printf("二级指针第三种内存模型排序后\n");

    printArray09(myArray, 4);

    system("pause");

    }

    展开全文
  • 1.用指针做函数参数申请动态内存的问题//如果函数参数指针,不能用一级指针做函数参数实现申请动态内存void getMemory(char *p, int num){p = (char *)malloc(sizeof(char)*num);}void main(){char *str = NULL;...

    1.用指针做函数参数申请动态内存的问题

    //如果函数参数是指针,不能用一级指针做函数参数实现申请动态内存

    void getMemory(char *p, int num)

    {

    p = (char *)malloc(sizeof(char)*num);

    }

    void main()

    {

    char *str = NULL;

    getMemory(str, 20);

    strcpy(str, "code");

    cout << str;

    system("pause");

    }//出错

    然而

    //用二级指针为指针申请内存,用二级指针做函数参数可以申请成功

    void getMemory1(char **p, int num)

    {

    *p = (char *)malloc(sizeof(char)*num);

    }

    void main()

    {

    char *str = NULL;

    getMemory(&str);

    strcpy(str, "code");

    cout << str;

    system("pause");

    }

    2.二级指针做函数参数简介修改变量的值

    #include

    using namespace std;

    struct Teacher

    {

    char name[20];

    int age;

    };

    int getTeacher(Teacher **p)

    {

    Teacher *tmp = NULL;

    if (p == NULL)

    {

    return -1;

    }

    if (tmp == NULL)

    {

    return -2;

    }

    tmp->age = 23;

    *p = tmp;//p是实参地址,*p间接修改实参的值

    //用二级指针修改一级指针的值,用一级指针修改零级指针的值

    }

    void FreeTeacher(Teacher *p)

    {

    if (p == NULL)

    {

    return;

    }

    free(p);

    }

    int main()

    {

    Teacher *pt = NULL;

    getTeacher(&pt);

    cout << pt->age << endl;

    FreeTeacher(pt);

    system("pause");

    return 0;

    }

    3.内存分区图:

    展开全文
  • 指针做函数参数自己编程实现字符串连接函数strcat()的功能。CQUPT题库 下面程序中存在比较隐蔽的错误,请通过分析和调试程序,发现并改正程序中的错误。 注意:请将修改正确后的完整源程序拷贝粘贴到答题区内。 ...

    用指针做函数参数自己编程实现字符串连接函数strcat()的功能。CQUPT题库
    下面程序中存在比较隐蔽的错误,请通过分析和调试程序,发现并改正程序中的错误。
    注意:请将修改正确后的完整源程序拷贝粘贴到答题区内。
    对于没有错误的语句,请不要修改,修改原本正确的语句也要扣分。
    当且仅当错误全部改正,且程序运行结果调试正确,才给加5分。
    经教师手工核对后,如果未用指针做函数参数编程,那么即使做对也不给分。
    改错时不能改变程序原有的意图,不能改变函数原型。

    #include <stdio.h>
    #define N = 80;
    void MyStrcat(char *dstStr, char *srcStr);
    main()
    {
        char s[N], t[N];
        printf("Input a string:\n");
        gets(s);
        printf("Input another string:\n");
        gets(t);
        MyStrcat(s, t);
        printf("Concatenate results:%s\n", s);
    }
    void MyStrcat(char *dstStr, char *srcStr)
    {
        while (*srcStr != '\0');
        {
            srcStr++;
        }
        while (*srcStr != '\0');
        {
            *dstStr = *srcStr;
            srcStr++;
            dstStr++;
        }
    }
    
    

    答案

    #include <stdio.h>
    #define N  80   //宏定义出现了格式错误
    void MyStrcat(char *dstStr, char *srcStr);
    main()
    {
        char s[N], t[N];
        printf("Input a string:\n");
        gets(s);
        printf("Input another string:\n");
        gets(t);
        MyStrcat(s, t);
        printf("Concatenate results:%s\n", s);
    }
    void MyStrcat(char *dstStr, char *srcStr)
    {
        while (*dstStr!= '\0') 
        {
            dstStr++;        //循环将S字符串的地址推向末尾
        }
        while (*srcStr != '\0')     //注意while后面没有分号,有分号不会进入内部循环语句!
        {
            *dstStr = *srcStr;     //将t的第一个往后依次赋给s ,*XX 代表指向取出值
            srcStr++;              //地址++
            dstStr++;              //地址++
        }
        *dstStr ='\0';
    }
    
    展开全文
  • 函数指针做函数参数

    2021-10-01 22:58:03
    之前一直不太明白函数指针做函数参数,为什么有回调函数。今天总算明白了,记录下。 函数指针做函数参数可以实现调用者与实现者进行了分离,在保证外部调用框架不变的情况下,只需要给不同的函数指针即可实现不同的...
  • C语言提高:函数指针做函数参数

    千次阅读 2021-07-13 21:06:01
    函数指针的三种定义与使用方式: https://yangyongli.blog.csdn.net/article/details/118711459 代码 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdli
  • #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> //回调函数 //第一个参数是一个万能指针,用来接收用户输入的数据------因为我们不知道用户会输入什么样的数据类型,...//回调函数的第二个参数 void myPri
  • 实例:#include #include void print(void * node){printf("%d\n", *(int *)node); //加星号报错,不加不报错,但是结果不对。//必须要转换成相应类型才能对...}void 关键字当函数返回值为空时,可以使用void。void...
  • 而且,将函数指针作为函数参数进行传递,还可以实现C语言下-相对于同一个函数指针在独立功能模块下的多态复用。举例如下, #include <stdio.h> #include <stdlib.h> int (*pFunc)(int m,int n); int (*...
  • 指向函数的指针通常作为函数参数来运用; 示例:随机生成n个整数,按升序或降序排序。 #include<stdio.h> #include<stdlib.h> #include<time.h> void create(int *arr,int n); void output(int *...
  • 在之前的讲习中我们学习了C语言中的指针变量以及函数参数的概念和作用,在实际的编程操作中往往会用到将指针变量作为函数参数的情况,那么究竟怎样把指针变量作为函数参数呢?下面课课家笔者就为大家讲解如何将指针...
  • 知识点:行指针,用行指针作为函数参数, 在函数中可以访问主函数中的二维数组,也可以修改这个二维数组中各元素值。 Problem: 定义一个函数将 4 ×4矩阵中的右上三角元素都设置成0,其余元素值不变。 。 Input: 以...
  • 当实参是结构体类型指针时,形参就需要使用指向结构体类型的指针变量,修改形参所指向的内存数据就会修改到实参数据。 #include<stdio.h> typedef struct _stu { int number; char name[20]; int score[2];...
  • 练习03-17-02 输出样例: The matrix of score: 22.00 75.00 74.00 53.00 9.00 95.00 48.00 60.00 85.00 18.00 32.00 30.00 The average score of whole student = 50.08 The scores of first student: ...
  • 指针用作函数参数 以前我们学过的函数参数要么是基本数据类型的变量,要么是类的对象,又或者是数组名,前几讲学到的指针同样可以用作函数参数指针作函数形参时,我们调用此函数将实参值传递给形参后,实参和形参...
  • 一、结构体作为函数参数、 二、结构体指针作为函数参数、 三、完整代码示例、
  • 满意答案#include #include #include void niXuArr(char arr[]);char * niXuPoint(char *p);int main(void){char arr[] = {"abcdefghigk"}, *p = "you are the first";printf("逆序前:%s\n逆序后:", arr);...
  • 数组指针作为函数参数第五章中我们介绍过用数组名作为函数参数的情况。数组名代表数组的起始地址,用数组名作参数传递的是地址。既然地址可以作为函数参数,那么指向数组元素的指针变量当然也可以作为函数参数。例...
  • 使用指针变量作为函数参数|地址传递与指针传递实例总结地址传递值传递错误写法1错误写法2 地址传递 指针类型可以作为函数参数的类型,这时视为把变量的地址传入函数。如果在函数中对这个地址的元素进行改变,原先的...
  • #includevoidswap(int*p,int*p2);/*propotypesdeclaration*/voidmain(){inta1,a2,*ptr1,*ptr2;printf("Entertwointeger(separatebycommas):\n");scanf("%d,%d",&a1,&a2);/*entera1anda...
  • 1、结构体指针 作用:通过指针访问结构体中的成员。 利用操作符:可以通过结构光指针访问结构体属性。 示例: #include <iostream> using namespace std; /// <summary> /// 定义学生结构体 /// </...
  • 指针作为函数参数,交换两个变量的值。 #include <stdio.h> /* 形参为指针 */ //begin //end int main( ) { int a, b, *p, *q; scanf("%d%d", &a, &b); /* 输入变量a、b的值 */ p = &a;...
  • 1 指针作为函数参数 void (const int* a){ ... } int main(){ int array; void(array) 指向常量的指针做形参,指针指向的内容不可修改 2 指针类型的函数 形参是指针,实参可以是指针/地址; 函数返回值是指针,...
  • 既然函数指针变量是一个变量,当然也可以作为某个函数参数来使用的。所以,你还应知道函数指针是如何作为某个函数参数来传递使用的。一个实例:要求:我要设计一个CallMyFun函数,这个函数可以通过参数中的函数...
  • i 用字符指针函数参数编程实现如下功能:在字符串中删除与某字符相同的字符。 **输入格式要求:"%s" 输入提示信息: "Input a string:" "Input a character:" **输出格式要求:"Results:%s\n" 程序运行示例1如下:...
  • 下面程序的功能是用指针变量作函数参数编程计算任意m×n阶矩阵的转置矩阵。要求用指向一维数组的指针变量即二维数组的行指针函数参数。程序的运行结果如下:Please enter matrix:1 2 3 4↙1 2 3 4↙1 2 3 4↙The ...
  • /* 定义一个指针变量p,说明它是一个指向一个包含4个 整型变量一维数组的指针 */ int n; /* 定义形式参数n为整形 */ { int i; /* 定义用于循环的变量i */ for (i=0;i;i++ ) /* 这里循环4次用于打印一个同学的4门课...
  • 指针加加 #include <stdio.h> #include <stdlib.h> #include <string.h> void setDataCond(int *p, unsigned int condi) { if (condi % 2) { *p = condi * 10; p++; } } void ...
  • 该楼层疑似违规已被系统折叠隐藏此楼查看此楼为了增加参数调用的灵活性,可以利用结构体指针传递多个不同的参数进入C语言函数体。最著名的例子就是用Win32APIHANDLE CreateThread(LPSECURITY_...
  • #include <stdio.h> void swap(int *pa, int *pb); int main() { int a, b; scanf("%d%d", &a, &b); swap(&a, &b); printf("%d %d", a, b); return 0; } void swap(int *pa, int *pb) ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 884,005
精华内容 353,602
关键字:

指针做函数参数