函数指针;回调函数; 预处理;静态库、动态库;递归函数;面向接口编程
函数指针

函数指针 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<stdlib.h> void func(int a ,char c) { printf("hello world\n"); } void test01() { //1、先定义出函数类型,再通过类型定义函数指针 typedef void(FUNC_TYPE)(int, char); FUNC_TYPE * pFunc = func; //pFunc(10, 'a'); //2、定义出函数指针类型,通过类型定义函数指针变量 typedef void( * FUNC_TYPE2)(int, char); FUNC_TYPE2 pFunc2 = func; //pFunc2(20, 'b'); //3、直接定义函数指针变量 void(*pFunc3)(int, char) = func; pFunc3(30, 'c'); }

函数指针 和 指针函数 区别:
函数指针:这是一个指针,是指向了函数的指针
指针函数:这时一个函数,函数返回值是指针

函数指针的数组 void func1() { printf("func1 调用了\n"); } void func2() { printf("func2 调用了\n"); } void func3() { printf("func3 调用了\n"); } void test02() { void(*pArray[3])(); pArray[0] = func1; pArray[1] = func2; pArray[2] = func3; for (int i = 0; i < 3;i++) { pArray[i](); } } int main(){ //test01(); test02(); system("pause"); return EXIT_SUCCESS; }
回调函数
回调函数:函数指针作为函数参数

回调函数示例 ======================================================== //提供一个打印函数,可以打印任意类型的数据 void printText( void * data , void(*myPrint)(void *) ) { myPrint(data); } void myPrintInt(void * data) { int * num = data; printf("%d\n", *num); } //------------------------------------------------------ struct Person { char name[64]; int age; }; void myPrintPerson(void * data) { struct Person * p = data; printf("姓名: %s 年龄: %d\n", p->name, p->age); } //------------------------------------------------------ int main(){ int a = 10; printText(&a, myPrintInt); //回调函数,手动传入函数指针 //------------------------------------------------------ struct Person p = { "Tom", 18 }; printText(&p, myPrintPerson); //打印了另一种类型 system("pause"); return EXIT_SUCCESS; }

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <malloc.h> #include <math.h> #include <time.h> //提供一个函数,实现对任意类型的数组进行排序,排序规则利用选择排序,排序的顺序 用户可以自己指定 void sort_int_arr(void* arr,int size,int arr_len) { //使用选择排序 int min; int tmp; for (int i = 0; i < arr_len; i++) { min = i; for (int j = 1; j + i < arr_len; j++) //循环获取最小下标 { if (*((int*)arr + min) > *((int*)arr + i + j)) { min = i + j; } } if (min != i) //如果当前下标的数有变化,那么说明不是最小数,需要进行交换 { tmp = *((int*)arr + i); *((int*)arr + i) = *((int*)arr + min); *((int*)arr + min) = tmp; } } } void sort_double_arr(void* arr, int size, int arr_len) { //其实和sort_int_arr是基本相同的,完全是可以写在同一个函数里的;这里只是为了展示回调函数的功能,特别写成了2个函数 //使用选择排序 int min; int tmp; for (int i = 0; i < arr_len; i++) { min = i; for (int j = 1; j + i < arr_len; j++) //循环获取最小下标 { if (*((double*)arr + min) > *((double*)arr + i + j)) { min = i + j; } } if (min != i) //如果当前下标的数有变化,那么说明不是最小数,需要进行交换 { tmp = *((double*)arr + i); *((double*)arr + i) = *((double*)arr + min); *((double*)arr + min) = tmp; } } } void my_sort_array(void (*my_sort_arr)(void* arr, int size, int arr_len), int arr[], int size, int arr_len) { my_sort_arr(arr,size,arr_len); } int main() { int arr[] = { 444,555,999,53523,4327948,33,4 }; int size = 4; int arr_len = sizeof(arr) / size; printf("排序前:"); for (size_t i = 0; i < arr_len; i++) { printf("%d\t",arr[i]); } printf("\n"); my_sort_array(sort_int_arr,arr,size,arr_len);//对int类型数组进行排序 printf("排序后:"); for (size_t i = 0; i < arr_len; i++) { printf("%d\t", arr[i]); } printf("\n"); //------------------------------------------------- double arr2[] = {1111111.3,2222.2,200,500,333.333,9666.345566}; int size2 = 8; int arr_len2 = sizeof(arr2) / size2; printf("排序前:"); for (size_t i = 0; i < arr_len2; i++) { printf("%lf\t", arr2[i]); } printf("\n"); my_sort_array(sort_double_arr, arr2, size2, arr_len2);//对double类型数组进行排序 printf("排序后:"); for (size_t i = 0; i < arr_len2; i++) { printf("%lf\t", arr2[i]); } printf("\n"); system("pause"); return EXIT_SUCCESS; }
预处理

include;宏定义;条件编译;一些特殊的预定宏 =================================================================================== C语言对源程序处理的四个步骤:预处理、编译、汇编、链接。 预处理是在程序源代码被编译之前,由预处理器(Preprocessor)对程序源代码进行的处理。 预处理阶段会将#include、宏定义等进行展开,即将import头文件内所有内容、展开宏定义 #include <>常用于包含库函数的头文件; #include ""常用于包含自定义的头文件; ------------------------------------------------------------------------------------- 宏展开:在预编译时将宏名替换成字符串的过程 宏定义 宏定义,只在宏定义的文件中起作用。 说明: 1) 宏名一般用大写,以便于与变量区别; 2) 宏定义可以是常数、表达式等; 3) 宏定义不作语法检查,只有在编译被宏展开后的源程序才会报错; 4) 宏定义不是C语言,不在行末加分号; 5) 宏名有效范围为从定义到本源文件结束; 6) 可以用#undef命令终止宏定义的作用域; 7) 在宏定义中,可以引用已定义的宏名; 无参数的宏定义(宏常量) #define NUM 100 //在编译预处理时,将程序中在该语句以后出现的所有的num都用100代替。 带参数的宏定义(宏函数) 在项目中,经常把一些短小而又频繁使用的函数写成宏函数,这是由于宏函数没有普通函数参数压栈、跳转、返回等的开销,可以调高程序的效率。 #define SUM(x,y) (( x )+( y )) 注意: 1) 宏的名字中不能有空格,但是在替换的字符串中可以有空格。ANSI C允许在参数列表中使用空格; 2) 用括号括住每一个参数,并括住宏的整体定义。 3) 用大写字母表示宏的函数名。 4) 如果打算宏代替函数来加快程序运行速度。假如在程序中只使用一次宏对程序的运行时间没有太大提高。 =================================================================================== 条件编译 测试存在: #ifdef 标识符 程序段1 #else 程序段2 #endif ------------------------------- 测试不存在 #ifndef 标识符 程序段1 #else 程序段2 #endif -------------------------------- 根据表达式定义 #if 表达式 程序段1 #else 程序段2 #endif ---------------------------------------------------------------------------------------------- 一些特殊的预定宏 C编译器,提供了几个特殊形式的预定义宏,在实际编程中可以直接使用,很方便。 // __FILE__ 宏所在文件的源文件名 // __LINE__ 宏所在行的行号 // __DATE__ 代码编译的日期 // __TIME__ 代码编译的时间
静态库、动态库

静态库配置、使用;动态库配置、使用 ==================================================================================================== 静态库、动态库 库是已经写好的、成熟的、可复用的代码。每个程序都需要依赖很多底层库,不可能每个人的代码从零开始编写代码,因此库的存在具有非常重要的意义。 在我们的开发的应用中经常有一些公共代码是需要反复使用的,就把这些代码编译为库文件。 ---------------------------------------------------------------------------------------- 静态库配置: 1.配置过程其实和写C项目大体上是相同的,也需要些.h和.c文件 2.生成项目时,生成.lib文件 3.将.lib、.h文件交给用户,即放在用户编写的C项目中(这个.h文件仅仅只是相当于一个说明文件) 4.用户将自己的C项目生成exe后,该exe可以独立运行(.lib文件的内容已经被打包进exe) ----------------------------------------------------------------------------------------- 动态库配置: 1.配置过程其实和写C项目大体上是相同的,也需要些.h和.c文件 2.生成项目时,生成.lib文件、.dll文件 .lib文件和静态库.lib文件不同:动态库的.lib文件只会放变量的声明和导出函数的声明;函数实现提放在.dll文件中 3.将.lib文件、.dll文件、.h文件交给用户,即放在用户编写的C项目中(这个.h文件仅仅只是相当于一个说明文件) 4.用户将自己的C项目生成exe后,该exe不能独立运行(因为依赖.dll文件) #C高级编程讲义.doc 02.C语言高级编程--》C高级编程day07
递归函数
C通过运行时堆栈来支持递归函数的实现。递归函数就是直接或间接调用自身的函数。
面向接口编程
C高级编程讲义.doc
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!