二、库函数 1、标准库和头文件 各种编译器的标准库中提供了⼀系列的库函数,这些库函数根据功能的划分,都在不同的头文件中进行了声明。同时,库函数的学习不要着急⼀次性全部学会,慢慢学习,各个击破就行。...(返回平方根) 2.2.2 头文件包含 库函数是在标准库中对应的头文件中声明的,所以库函数的使用,务必包含对应的头⽂件。...1、单个文件 ⼀般我们在使用函数的时候,直接将函数写出来就使用了。函数的定义在函数调⽤之前,没啥问题。那如果我们将函数的定义放在函数的调用后边就会出现问题。...递归与迭代 在C语⾔中每⼀次函数调⽤,都要需要为本次函数调⽤在栈区申请⼀块内存空间来保存函数调⽤期间的各种局部变量的值,这块空间被称为运⾏时堆栈,或者函数栈帧。...函数不返回,函数对应的栈帧空间就⼀直占⽤,所以如果函数调⽤中存在递归调⽤的话,每⼀次递归函数调⽤都会开辟属于⾃⼰的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。
,一般写作: void (*add2)(int) = add1; //add2是一个函数指针,解引用后就是一个函数,所以解引用后用来承接一个函数 //或者 void (*add2)(int); add2...所以p是指向函数指针数组的指针 回调函数 如果一个函数B,其指针作为另一个函数A的参数,并再A中被调用了,那么B就称为回调函数。...//回调函数类型名称重命名 void claculateSum(int a, int b,Callback cb) { int sum = a + b; cb(sum); //调用回调函数...,将结果传递给回调函数 } char* printSum(int sum)//定义回调函数 { printf("计算结果为:%d\n",sum); return "回调函数已调用\n";...,不同架构的计算机只需修改这个头文件即可,而无需修改代码。
【示例】计算平方根 double sqrt (double x); //sqrt 是函数名 //x 是函数的参数,表⽰调⽤sqrt函数需要传递⼀个double类型的值 //double 是返回值类型 -...如果在这些地方使用return语句,会导致语法错误。...,否则会导致编译错误。...数组传参不会创建新的数组:当将数组作为参数传递给函数时,函数内部使用的是原始数组的地址,而不是创建一个新的数组。这意味着对形参数组的修改会直接影响原始数组。...形参操作的数组和实参的数组是同一个数组:当将数组作为参数传递给函数时,形参操作的是原始数组的副本。也就是说,形参数组和实参数组指向的是同一个数组。因此,对形参数组的修改会影响到实参数组。 5.
dll,dll中设置的回调函数使,当键盘按了1,那么就会触发一个MessageBox。...,在之后EnumProcesses函数调用会将当前所有进程id放入数组 DWORD NeededProcessesId = 0; //在之后EnumProcesses函数调用后会将实际需要的进程数组的大小赋值给它...hDll句柄中的KeyboardProc函数的地址 if (KeyboardProc == NULL) { printf("获取到回调函数地址失败\n"); exit(0); } else..., hDll, TargetWindowThreadId); //将dll注入目标线程,设置函数指针指向写好的键盘消息回调函数 //第一个参数输入钩子类型 //第二个参数根据不同的钩子类型,要输入不同类型的回调函数地址...,返回进程id DoInject()函数是执行注入的过程,需要知道被注入的线程的id EnumWindowsProc()函数是回调函数,对于每个已存在的窗口,判断其进程id是否与目标进程id相同,如果是
(a++):(b++)) //(5,4) ((5,使用后++,变6)>(4,使用后++,变为5)?...④宏可能会带来运算符优先级的问题,导致程容易出现错。因此,不能吝啬括号。 总结宏和函数的对比: 属 性 #define定义宏 函数 代 码 长 度 每次使用时,宏代码都会被插入到程序中。...调 试 宏是不方便调试的 函数是可以逐语句调试的 递 归 宏是不能递归的 函数是可以递归的 宏命名的约定: 一般来说,一般都是英文全大写来命名宏。不过也有会采用小写,我们需要懂得分辨。...}; for (i = 0; i < 10; i++) { arr[i] = i; #ifdef __DEBUG__ printf("%d\n", arr[i]);//为了观察数组是否赋值成功...对于头文件来说,有以下两种形式: ①#include :以来包含头文件名的,直接去标准路径下查找头文件、 ②#include "......"
程序员需要在使用完动态数组后手动释放其内存空间,否则可能会导致内存泄漏的问题,进而导致程序崩溃或者运行缓慢。因此,在使用动态数组时,程序员需要特别注意内存管理的问题。...读者需自行创建头文件dynamic.h并拷贝如下动态数组代码实现; #include #include struct DynamicArray {...= NULL) { for (int x = 0; x curr_size; x++) { // 调用回调函数并将数组指针传递过去...然后使用RemoveByPosDynamicArray函数根据下标移除第一个元素,使用RemoveByValueDynamicArray函数根据元素的值移除第二个元素,其中使用myCompare回调函数对比元素...最后使用ForeachDynamicArray函数遍历所有元素,并使用MyPrint回调函数输出元素的值。最终销毁动态数组,释放内存。
程序员需要在使用完动态数组后手动释放其内存空间,否则可能会导致内存泄漏的问题,进而导致程序崩溃或者运行缓慢。因此,在使用动态数组时,程序员需要特别注意内存管理的问题。...读者需自行创建头文件dynamic.h并拷贝如下动态数组代码实现;#include #include struct DynamicArray{ void *...= NULL) { for (int x = 0; x curr_size; x++) { // 调用回调函数并将数组指针传递过去...然后使用RemoveByPosDynamicArray函数根据下标移除第一个元素,使用RemoveByValueDynamicArray函数根据元素的值移除第二个元素,其中使用myCompare回调函数对比元素...最后使用ForeachDynamicArray函数遍历所有元素,并使用MyPrint回调函数输出元素的值。最终销毁动态数组,释放内存。
这个文件里面可以继续扩展多学生数据增删改实现函数。 感谢林颖贤老师的指正,原SaveSTUFile文件里面多写了换行符,导致文件再次读出,最后一行是0。...2.3 主函数文件main.c 主要实现分散在各个c文件中的函数调用及一些主要数组、全局变量定义。...建议用数组地址做函数参数传递,效率更高。注意点: 菜单单独封装一个函数,确实比较好用,如果需要修改菜单选项,只要Menu函数修改即可。这个学习班上同学做法。确实不错。...学会文件中数据读取,存入结构体数组,如上述的int ReadSTUFile(FILE *fp,STU stu[]);函数 学会在结构体数组增删改、查找、排序操作。...如void SaveSTUFile(STU *stuPtr,int total,FILE *fp) 4.项目文件容易出现问题 自定义头文件定义变量,其他文件又都包含头文件,导致变量多次定义,如:
10个元素,用指针越界访问到第12个元素,就会成野指针了 指针指向的空间被释放了 下面这个可以运行,但是也是个野指针,很危险 这个函数,返回了n的地址后,这个函数的空间就被释放了,p指向了一个被释放的空间...,就是野指针了 避免野指针 当指针没有地址初始化,我们只需要给个NULL就可以避免野指针了 assert断言 使用assert函数我们需要下面这个头文件 #include assert.h...如果是我们想让assert全部失效我们可以添加下面这个头文件 #define NDEBUG 然后,重新编译程序,编译器就会禁⽤⽂件中所有的 assert() 语句。...如果程序⼜出现问题,可以移 除这条 #define NDBUG 指令(或者把它注释掉),再次编译,这样就重新启⽤了 assert() 语 句。...我们可以看到p是NULL,加上这个头文件,assert失效了,如果有多个assert那么全部失效 当然我们在Release环境下执行会自动过滤assert 传值调⽤和传址调⽤ 传值调用 传值调用就是传数值到函数里
第二次函数调用Add,虽然ret没有接受,但是因为在第一次函数调用后,ret就已经是c的别名了,是指向c的引用,由于函数栈帧空间的复用性,第二次Add的调用还是在上一次的空间,此时c更改了值,那么ret...但是这是不确定的,因为在不同的编译器下,函数栈帧调用后,会不会立即清空空间,所以值是不确定的,如果销毁了,那么ret引用的值就是个随机值,如果没销毁,那就是函数正常的返回值....传值的优点是简单、直观,不会对原始数据产生任何影响。但是,传值会导致参数的副本被创建,如果参数较大,传值的效率可能会比较低。 传引用的优点是效率高,因为不需要创建参数的副本。...同时,传引用可以直接修改原始数据,对原始数据产生影响。但是,需要注意的是,如果函数内部不需要修改参数的值,传引用可能会导致意外的修改,因此需要谨慎使用。...返回值的优点是简单、直观,不会对原始数据产生任何影响。但是,返回值会导致结果的副本被创建,如果结果较大,返回值的效率可能会比较低。 返回引用的优点是效率高,因为不需要创建结果的副本。
这些指针都在boost库的头文件中,如下所示: #include using namespace boost; 1.3 scoped_ptr 该类型指针和auto_ptr...使用后会使得代码相对简单且不会增加多余操作。...1.5.1 shared_ptr使用方法 shared_ptr指针是最接近原始指针的。...shared_ptr退出作用域后调用回调函数,如下: void fun(void *p){} shared_ptr p((void *0),fun); 除此之外,shared_ptr...1.7.1 weak_ptr使用方法 weak_ptr和shared_ptr共用可以通过shared_ptr或者weak_ptr对象构造,使用时不会产生引用计数增加,析构时也不会导致引用计数的减少。
比如http://blog.csdn.net/sunboyljp/archive/2009/12/31/5110639.aspx c++ 头文件中的定义: NPD_API int NP_Init()...2、重写结构体的时候,之前有指明类型长度或数组长度的地方,也要进行相应的标注,要不也会导致内存错误。 ...最后是在C++那边做了修改解决的,通过制定模块定义 (.def) 文件,统一制定导出函数对应的名称。返回值为结构体指针的函数用IntPtr也能使用了。 ..., int to_port, string server_id, string user_id, string user_name, IntPtr user_obj_param); 4、后来还遇到个回调函数导致的崩溃问题...做程序就怕出现问题,出现问题就怕不知道原因,知道原因了就好找解决的办法啦!
ffmpeg_main;主要是为了避免两个main函数存在 2、计数器置零问题 (ffmpeg.c的代码中会访问空属性导致程序崩溃) 在 ffmpeg.c 中 找到 ffmpeg_cleanup 方法,...image 这种方法的缺点: 执行完 ffmpeg 的 main 函数后会回调一个code,这个回调是用于判断命令指定过程中是否执行错误的回调。...include "LEYFFmpegConverOC.h" 2、在static int open_input_file(OptionsContext *o, const char *filename)函数的恰当位置添加回调..., int64_t timer_start, int64_t cur_time)函数的恰当位置添加回调 setCurrentTime(buf.str); 我放在 fflush(stderr)语句之前。...转码结束 ffmpeg.c 1、添加头文件 #include "LEYFFmpegConverOC.h" 2、在ffmpeg_cleanup函数的term_exit()语句之前添加stopRuning
显然声明的时候不会出现问题,执行回调函数的时候也不可能出现问题。...this 隐式绑定到class page this.MessageCallBack('发给注册页面的信息') } } 回调函数this丢失的解决方案: bind绑定回调函数的this...指向: 这是典型bind的应用场景, 绑定this指向,用做回调函数。...this.pageClass = new Page(this.handleMessage.bind(this)) // 绑定回调函数的this指向 PS: 这也是为什么react的render函数在绑定回调函数的时候...(数字,字符串,布尔值)的 this 会指向该原始值的实例对象 } // JavaScript权威指南判断是否为类数组对象 function isArrayLike(o) {
一般形式为: 类型说明符被调函数名(类型形参,类型形参…); 或 类型说明符被调函数名(类型,类型…); 注意:其末尾“;”不能省 例如:int max(int a,int b); 或 int max...: (1)被调函数的返回值是整型或字符型时(返回值自动按整型处理) (2)当被调函数的函数定义在主调函数之前时 (3)在所有函数定义之前,在函数外预先说明了各个函数的类型 例2:(10-09-24)有以下程序...5次,每次调用后的值返回值累加到s上。...所以第一次调用后,x的值为2,返回后s的值为2,第二次调用后,x的值为2*2=4,返回后s的值为2*4=8,第三次调用后,x的值为4*2=8,返回后s的值为8*8=64,故选D。...【解析】对每一类库函数,都有相应的头文件名,调用某个库函数时,用户在源程序中须用include命令包含其头文件名。
// 'Page' this指向错误 } } new PageA() 回调函数this为何会丢失?...显然声明的时候不会出现问题,执行回调函数的时候也不可能出现问题。...回调函数this丢失的解决方案: bind绑定回调函数的this指向: 这是典型bind的应用场景, 绑定this指向,用做回调函数。...this.pageClass = new Page(this.handleMessage.bind(this)) // 绑定回调函数的this指向 PS: 这也是为什么react的render函数在绑定回调函数的时候...(数字,字符串,布尔值)的 this 会指向该原始值的实例对象 } // JavaScript权威指南判断是否为类数组对象 function isArrayLike(o) {
第二点就是宏他并没有类型安全检查就算是一个加法也有可能有人给你传俩个字符 第三点就是宏不方便调试,导致代码可读性差 所以在C++中就采用了内联函数和枚举来解决宏的使用的问题 以inline修饰的函数叫做内联函数...,编译时C++编译器会在调用内联函数的地方展开,没有函数调 用建立栈帧的开销,内联函数提升程序运行的效率。...其实函数在调用次数过多的情况下就不适合使用内联函数,这样就会导致代码膨胀到处都是重复的代码,从而使得可执行程序变大; 还有在函数的递归时也不能使用内联函数,函数栈帧是可以复用的,但内联函数一旦使用也会导致代码膨胀...f(int*)" << endl; } int main() { f(0); f(NULL); f((int*)NULL); return 0; } 诶这里使用指针 NULL 定义空值的时候就出现问题了...*)0); 所以新增了一个关键字 nullptr == ((void *)0); 注意: 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
当系统内存不足时,程序可能会出现性能下降、运行缓慢甚至崩溃的情况 1.2.2 free的使用 释放和回收动态内存的函数为 free ,声明在 stdlib.h 头文件中 传送门:free-C++参考...2.1 calloc calloc 函数也用来动态内存分配,但是它可以初始化动态内存的内容,声明在 stdlib.h 头文件中 传送门:calloc-C++参考 参数:num-元素个数,size...NULL,但这里的问题是,当它返回 NULL 时,原始的 ptr 所指向的内存块已经被释放(因为 realloc 在尝试重新分配失败时,会释放掉原始的内存块以避免内存泄漏),这就导致 ptr 变为 NULL...,并且之前通过 ptr 可访问的原始数据也丢失了,后续若再尝试使用 ptr 就会导致程序出错 代码2: 先将 realloc 函数的返回值赋给 p ,然后进行判断的做法更为稳妥,同样执行 p = realloc...),这样就可以避免丢失原始数据以及出现空指针错误 3.柔性数组 3.1 什么是柔性数组?
示例: #include #include //malloc函数所需要的头文件 int main() { //向内存申请10个整形所占的字节个数的空间,通过强转为...将上面的malloc代码改成calloc函数后: #include #include //malloc函数所需要的头文件 int main() { int* a...这时有两种情况: ①:原地扩容: 原地址后面有足够的空间支持扩容.这时,会占用后面未被分配的内存空间用于扩容. ②:异地扩容: 原地址后面的内存空间不够支持扩容,则需要找到另外一块内存空间,将数据拷贝过去...图解: 三、动态内存函数操作不当造成的错误: (1)访问空指针 对申请的空间忘记进行NULL指针判断,导致访问空指针 这里一次申请大量的内存空间,内存没有那么多,会申请失败,返回NULL指针....,导致一直占用内存空间.
)实现jni头文件里面定义的函数 2、注册原理 静态注册的原理是当加载动态库到jvm后,当Native方法第一次执行时会根据其方法名去匹配对应的C语言实现。...4、缺点 1)后期类名、文件名改动,头文件所有函数将失效,需要手动改,超级麻烦易出错 2)代码编写不方便,由于JNI层函数的名字必须遵循特定的格式,且名字特别长; 3)会导致程序员的工作量很大,因为必须为所有声明了...native函数的java类编写JNI头文件; 4)程序运行效率低,因为初次调用native函数时需要根据根据函数名在JNI层中搜索对应的本地函数,然后建立对应关系,这个过程比较耗时。...二、动态注册 1、注册步骤 1)建立java函数和C函数映射的数组(签名必须一致) 2)通过RegisterNatives注册映射数组 3)重写JNI_OnLoad方法,动态库加载时就会调用JNI_OnLoad.../lang/String;", (void*)GetstringFromJNI },//绑定 }; //此函数通过调⽤RegisterNatives⽅法来注册我们的函数 static int registerNativeMethods
领取专属 10元无门槛券
手把手带您无忧上云