完全理解C语言函数
文章目录
- 1.函数是什么
- 2.C语言中的函数分类
- 2.1 库函数
- 2.1.1 如何使用库函数
- 2.2自定义函数
- 3.函数的参数
- 3.1 实际参数(实参)
- 3.2 形式参数(形参)
- 4.函数调用
- 4.1传值调用
- 4.2 传址调用
- 4.3 练习
- 5.函数的嵌套调用和链式访问
- 5.1 嵌套调用
- 5.2 链式访问
- 6.函数的声明和定义
- 6.1 函数声明
- 6.2 函数的定义
- 7.函数递归
- 7.1 什么是递归
- 7.2 递归的两个必要条件
- 7.2.1 练习1
- 7.2.2 练习2
- 7.3递归与迭代
- 7.3.1 练习3
- 7.3.2 练习4
1.函数是什么
在数学中,我们经常能听到各种函数,什么指数函数,对数函数,三角函数…
在维基百科中对函数的定义为:子程序
- 在计算机科学中,子程序(subroutine, subprogram, callable unit),是一个大型程序中的某部分代码,由一个或多个语句块组成。它负责完成某项特殊任务,而且相较于其他代码,具有相对的独立性。
- 一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库
程序中的函数就相当于一座工厂,你提供给工厂一些原材料,工厂就会给你想要的家具。
2.C语言中的函数分类
1.库函数
2.自定义函数
2.1 库函数
为什么要有库函数?
1.当我们在学习C语言编程的时候开始,总是会在屏幕上打印各种的信息,为了打印信息我们用到了,将信息按照一定个数打印到屏幕的printf
2.当我们想要对一个数求它的根号时的sqrt
3.当我们想要对一个数求n次幂时的pow
当我用上面这些函数的时候有没有想到为什么他们可以实现我们的需求。
这是因为,在我们开发的过程当中每个程序员都可能会用到,为了支持可移植和提高按程序的效率,C语言提高提供了一系列类似的库函数,方便程序员进行软件开发。
一个方便学习了解库函数的网站:cplusplus.com
通过这个网站去了解库函数的功能 名字 参数 返回值。
简单总结,C语言常用的库函数有:
IO函数(输入输出函数)
字符串操作函数
字符操作函数
内存操作函数
时间/日期函数
数学函数
其他库函数
如何使用文档学习库函数
以strcpy为例
在使用库函数时一定要包含对应的头文件
小知识
C语言并不是直接实现库函数 而是提供了C语言的标准和库函数的约定
如:功能 名字 参数 返回值
库函数的实现一般是由编译器去实现
2.1.1 如何使用库函数
对应库函数是不需要全部记住的,当你需要的时候去查资料就可以了。
查询查询工具:
MSDN(Microsoft Developer Network)
cplusplus.com
cppreference.com (英文版)
cppreference.com (中文版)
对于学习编程来说,英语也很重要。
2.2自定义函数
尽管C语言给我们提供了丰富的库函数,但是对于我们要实现的很多功能来说是远远不给的。为此更加重要的是自定义函数
自定义函数和库函数一样,有函数名,返回值和函数参数。
但是不一样的是这些都是我们自己来设计的,这就给了程序员很大的发挥空间。
函数的组成
ret_type fun_name(paral)
{statement;//语句项
}
//ret_type 是返回类型
//fun_name 是函数名
//paral 是函数参数
举例例子,找出两个数中较大的一个数
#include <stdio.h>
int get_max(int x,int y)
{return x>y?x:y;
}
int main()
{int a = 0;int b = 0;scanf("%d %d",&a,&b);int max = get_max(a,b);printf("%d\n",max);return 0;
}
再来一个,交换两个数的值
#include <stdio.h>
void swap(int x,int y)
{int tmp = x;x = y;y = tmp;
}
int main()
{int a = 5;int b = 3;printf("交换前a = %d,b = %d\n",a,b);swap(a,b);printf("交换后a = %d,b = %d\n",a,b);return 0;
}
//打印结果
//交换前a = 5,b = 3
//交换后a = 5,b = 3
这是为什么呢?
3.函数的参数
3.1 实际参数(实参)
真实传给函数的参数,叫实参。
实参可以是:变量、常量、表达式、函数
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便于将这些值传递给形参。
3.2 形式参数(形参)
形式参数是指函数名括号中的变量,因为形式参数只有在函数被调用的过程中才能实例化(分配内存单元),所有叫形式参数。形式参数当函数调用之后就自动销毁了。因此形式参数只有在函数中有效。
这也就说明了当实参传递给形参时,形参只是实参的一份临时拷贝。对形参的改变是不会影响到实参的。这也就是在上面交换时a和b没能够交换成功的原因。
#include <stdio.h>
//错误写法
/*void swap(int x,int y)
{int tmp = x;x = y;y = tmp;
}*/
//正确写法
void swap(int* pa, int* pb)
{int tmp = *pa;*pa = *pb;*pb = tmp;
}
int main()
{int a = 5;int b = 3;printf("交换前a = %d,b = %d\n", a, b);swap(&a, &b);printf("交换后a = %d,b = %d\n", a, b);return 0;
}
//打印结果
//交换前a = 5,b = 3
//交换后a = 3,b = 5
下面对实参和形参进行分析:
#include <stdio.h>
void swap1(int x,int y)
{int tmp = x;x = y;y = tmp;
}
void swap2(int* pa, int* pb)
{int tmp = *pa;*pa = *pb;*pb = tmp;
}
int main()
{int a = 5;int b = 3;swap1(a, b);printf("swap1:a = %d,b = %d\n", a, b);swap2(&a, &b);printf("swap2:a = %d,b = %d\n", a, b);return 0;
}
//打印结果
//swap1:a = 5,b = 3
//swap2:a = 3,b = 5
swap1
和swap2
函数中的x,y,pa,pb
都是形式参数。在main函数中传给 swap1
的a,b
swap2
函数的 &a,&b
是实际参数。
调用vs2022的调试窗口,
代码对应的内存分配:
这里可以看到swap1
函数在调用的时候,x 和 y 拥有自己的空间,同时拥有了和实参一模一样的内容(图中所标xy的值已交换)。所以我们可以简单的认为:形参实例化后其实相当于实参的一份临时拷贝
4.函数调用
4.1传值调用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
4.2 传址调用
- 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
- 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
4.3 练习
1.写一个函数判断一个数是不是素数,输出100-200间所有的素数。
2.写一个数判断一年是不是闰年,输出1900·2000年间为闰年的年份。
3.写一个函数,实现一个整型有序数组的二分查找。
4.写一个函数,每调一次这个函数,就会将 num 的值增加1。
维基百科对素数 的定义:
质数,又称素数,指在大于1的自然数中,除了1和该数自身外,无法被其他自然数整除的数(也>可定义为只有1与该数本身两个正因数的数)。
试除法
一个数x = a*b 若为合数,一定存在其中一个约数a或b大于sqrt(x)。所以我们只需要枚举到sqrt(x)就可以了。如果在2~sqrt(x)都没有能够整除x的数,那就说明了x为素数。
//1.写一个函数判断一个数是不是素数,输出100-200间所有的素数。
#include <stdio.h>
#include <stdbool.h>// 布尔值(bool)的头文件
#include <math.h>//sqrt的头文件
bool is_prime(int x)
{for(int i = 2;i<=sqrt(x);++i){if(x%i==0)return false;}return x>=2;
}
int main()
{for(int i = 100;i<=200;++i){if(is_prime(i)){printf("%d ",i);}}return 0;
}
//打印结果:
//101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
//2.写一个数判断一年是不是闰年,输出1900·2000年间为闰年的年份。
#include <stdio.h>
#include <stdbool.h>// 布尔值(bool)的头文件
bool is_leap_year(int year)
{return (year%4==0&&year%100!=0||year%400==0);
}
int main()
{for(int i = 1900;i<=2000;++i){if(is_leap_year(i)){printf("%d ",i);}}return 0;
}
//打印结果:
//1904 1908 1912 1916 1920 1924 1928 1932 1936 1940 1944 1948 1952 1956 1960 1964 1968 1972 1976 1980 1984 1988 1992 1996 2000
二分查找
二分查找是在有序数里面找一个数最优的一个算法,下面为二分查找的原理。
就像猜数字的游戏,我随便给你给一百以内的数字,比如62。
开始你在猜的时候,肯定会去猜50,以此来排除一半的数,当得知50小了,那1-50就全排除了。继续猜75,猜大了说明75-100都不可能,继续猜62,答对啦。这就是二分查找的精髓,每次排除剩余数的一半。如果需要在2的32次方中猜一个数,也最多只需要猜测32次就可以了。
//3.写一个函数,实现一个整型有序数组的二分查找。
#include <stdio.h>
int binary_search(int arr[],int x,int n)
{int left = 0,right = n-1;while(left<=right){int mid = (left+right)/2;if(arr[mid] == x){return mid;}else if(arr[mid]>x){right = mid-1;}else{left = mid+1;}}return -1;//没找到返回-1
}
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9,10};int x = 7;int ret = binary_search(arr,x,10);if(ret == -1){printf("没找到!\n");}else{printf("找到了,下标为%d\n",ret);}return 0;
}
//打印结果:
//找到了,下标为6
//4.写一个函数,每调一次这个函数,就会将 num 的值增加1。
#include <stdio.h>
//定义一个全局变量num
int num = 0;
void test()
{num+=1;
}
int main()
{test();test();printf("%d ",num);return 0;
}
//打印结果:
//2
5.函数的嵌套调用和链式访问
函数和函数之间可以根据实际的需求进行组合,也可以互相调用。
5.1 嵌套调用
#include <stdio.h>
void print()
{printf("hello\n");
}
void test()
{print();
}
int main()
{test();return 0;
}
函数可以嵌套调用但不可以嵌套定义。
//以下为嵌套定义,不能这样写!
#include <stdio.h>void test()
{void print(){printf("hello\n");}
}
int main()
{test();return 0;
}
5.2 链式访问
把一个函数的返回值作为另一个函数的参数.
//代码1
#include <stdio.h>
#include <string.h> //strlen的头文件
int main()
{printf("%d\n",strlen("hello"));return 0;
}
//打印结果:
//5//代码2
#include <stdio.h>int main()
{printf("%d",printf("%d",printf("%d",43)));//printf 返回是字符个数return 0;
}
//打印结果:
//4321
6.函数的声明和定义
6.1 函数声明
1.告诉编译器有一个函数叫什么,参数是什么,返回 类型是什么.但是具体是不是存在,函数声明决定不了.
2.函数的声明一般出现在函数的使用之前.要满足先声明后使用
3.函数的声明一般要放在头文件中的.
6.2 函数的定义
函数的定义是指函数的具体实现,交代函数的功能实现.
以Add函数为例
test.h的内容
放置函数的声明
//函数的声明
int Add(int x,int y);
test.c的内容
放置函数的实现
//函数的实现
int Add(int x,int y)
{return x+y;
}
这是分文件的书写形式.
值得注意的是:函数定义也是一种特殊的声明,放前面就相当于声明.
7.函数递归
最简单的递归程序.
#include <stdio.h>
int main()
{printf("hello!\n");main();return 0;
}
//死循环打印hello!
//然后栈溢出导致程序死亡。
直白点说递归就是自己调用自己。
7.1 什么是递归
程序调用自身的编程技巧称为递归(recursion)
递归作为一种算法在程序设计语言中广泛应用.一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型问题层层转化为一个于原问题相似的规模较小的问题来求解.
递归策略
只需要少量的代码就可以描述出解题所需要的多重计算,大大的减少程序的代码量.
递归的主要思想在于:把大事化小
7.2 递归的两个必要条件
- 存在限制条件,当满足这个限制条件的时候,递归便不在继续。
- 每次递归调用之后越来越接近这个限制条件。
7.2.1 练习1
接受一个整型值(无符号),按照顺序打印它的每一位.
例如:
输入:1234 输出 1 2 3 4
问题拆分,我们要依次打印1 2 3 4。可以将问题拆分成,打印1的尾数,12的尾数,123的尾数,1234的尾数。这4个相似的问题,同时123可以由1234/10得到,其他类似。为此满足了递归的主要思想,把大事化小,且问题类似。所以代码里我们也要将大事化小,为此我们可以将传入的数/10后再调用该函数,但是要注意的是当最后传入的数是一位数时,除10就变成了0,题目可没有让我们打印0,所以我们要加一个限制条件,当传入的数满足大于9时才让它调用自己。写完递归的主要步骤还要完成题目所说的打印,所以最后我们应该打印传入数字的尾数,num%10。
#include <stdio.h>
void print(size_t num)
{if (num > 9)//数字为两位数{print(num / 10);}printf("%d ",num%10);
}
int main()
{size_t num = 1234;print(num);return 0;
}
//打印结果:
//1 2 3 4
当我们传入1234时,因为满足数字为两位数的条件,再次调用函数print传入123。又因为同样原因再次调用print传入12,又因为同样原因调用print传入1。注意此时,传入的数字已不满足条件,执行打印函数,打印1%10(1),完后本次函数执行完毕,返回上一层,执行打印函数12%10(2)完后,开始返回上一层,执行打印函数123%10(3)完后,开始返回上一层,执行打印函数1234%10(4)完后。完成任务,返回主函数main。根据下图理解。
7.2.2 练习2
编写函数不允许创建临时变量,求字符串的长度。
问题拆分:在求一个字符串长度时,以"hello"为例。我们求它的长度时,因为‘h’的长度肯定是1,所以我们是不是可以转化成求1+“ello”的长度。依次类推还可以写成1+1+“llo”的长度…
最后求到’\0’时,因为’\0’不能作为字符串长度所以+0。依照这个思路写成的代码就是这样。
#include <stdio.h>
/*
//迭代写法
size_t my_strlen(char* s)
{size_t count = 0;while(*s!='\0'){s++;count++;}return count;
}
*/
//递归写法
size_t my_strlen(char* s)
{if(*s == '\0')return 0;return 1+my_strlen(s+1);
}
int main()
{char ch[] = "hello!";size_t ret = my_strlen(ch);//数组名就是数组首元素的地址printf("%d\n",ret); return 0;
}
//打印结果:
//6
7.3递归与迭代
7.3.1 练习3
求n的阶乘。(不考虑溢出)
阶乘:n! = n*(n-1)*(n-2)*(n-3)…*3*2*1;
问题拆分
看着上面的式子,我们是不是可以把求n!转化成求n*(n-1)!呢。然后我们在同理就可以把问题一直拆分成一个个很小的相似的问题。代码如下:
#include <stdio.h>
int factorial(int n)
{if(n <= 1)return 1;return n*factorial(n-1);
}
/*
//迭代方法
int factorial(int n)
{int ret = 1;for(int i = 1;i<=n;++i){ret*=i}return ret;
}
*/
int main()
{int n = 0;scanf("%d",&n);int f = factorial(n);printf("%d\n",f);return 0;
}
在调试factorial函数时,如果参数过大,那就会报错:stack overflow(栈溢出)这样的信息。
系统分配给程序的栈空间是有限的,但如果出现了死循环或者(死递归),这样有可能导致一直开辟栈空间,最终产生栈空间耗尽的情况,做这样的现象我们称指为栈溢出。
7.3.2 练习4
求第n个斐波那契数 (不考虑溢出)
斐波那契数(部分):1 1 2 3 5 8 13 21 34 …
除第1和第2个外,后面的每个数都等于前两个数的和。所以代码如下:
#include <stdio.h>
int fib(int n)
{if(n<=2)return 1;return fib(n-1)+fib(n-2);
}
/*
//迭代方法
int fib(int n)
{int a = 1;int b = 1;int c = 1;for(int i = 2;i<n;++i){c = a+b;a = b;b = c;}return c;
}
*/
int main()
{int n = 0;scanf("%d",&n);int ret = fib(n);printf("%d\n",ret);return 0;
}
但是在用递归求解斐波那契数时:
- 如果我们计算第50个斐波那契数时会特别耗费时间,可是如果用迭代方法就很块,
为什么呢
其实在计算斐波那契数数时有很多的重复计算。
光是我列举出来的这几项里,f(47)就计算了3次。
利用程序来看看f(40) 里发(3)计算了几次吧。
#include <stdio.h>
int num = 0;
int fib(int n)
{if(n == 3)num++;if(n<=2)return 1;return fib(n-1)+fib(n-2);
}
int main()
{fib(40);printf("%d\n",num);return 0;
}
//打印结果:
//39088169//代码2,记忆化搜索,不作要求
/*#include <stdio.h>
#include <string.h>
int memo[55];//当你想求更大的数时,修改memo的数组长度即可。
int fib(int n)
{if (n <= 2)return 1;if (memo[n] != -1){return memo[n];}return memo[n] = fib(n - 1) + fib(n - 2);
}
int main()
{memset(memo, -1, sizeof memo);int n = 0;scanf("%d", &n);int ret = fib(n);printf("%d\n", ret);return 0;
}*/
如何解释上述问题呢?
1.递归写成非递归
2.使用static对象代替nonstatic局部变量。在递归函数设计中,可以使用static对象代替nonstatic局部对象(栈对象),这不仅可以减少每次递归调用和返回时产生和释放nonstatic对象的开销,而且static对象还可以保存递归调用的中间状态,并且可为各个调用层所访问。
提示:
- 许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。
- 但是这些问题的迭代实现可能比递归实现的效率更高,虽然代码的可读性稍微差些。
- 当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行开销。
课后作业
1.汉诺塔问题
2.青蛙跳台阶问题(类斐波那契)
完
相关文章:

完全理解C语言函数
文章目录 1.函数是什么2.C语言中的函数分类2.1 库函数2.1.1 如何使用库函数 2.2自定义函数 3.函数的参数3.1 实际参数(实参)3.2 形式参数(形参) 4.函数调用4.1传值调用4.2 传址调用4.3 练习 5.函数的嵌套调用和链式访问5.1 嵌套调…...

性能测试:JMeter与Gatling的高级配置
性能测试是软件开发过程中不可或缺的一部分,它帮助我们确保应用在高负载下仍能保持良好的响应时间和稳定性。本文将深入探讨两种流行的性能测试工具:Apache JMeter和Gatling,并提供详细的高级配置指南以及Java代码示例。 Apache JMeter 高级…...

Linux 软件管理
Linux 软件管理 在 Linux 系统中,RPM(Red Hat Package Manager)和 YUM(Yellowdog Updater, Modified)是用于软件包管理的重要工具。 RPM RPM 是由 Red Hat 公司开发的软件包管理系统。 RPM 软件包通常具有 .rpm 扩…...

五.核心动画 - 图层的变换(平移,缩放,旋转,3D变化)
引言 在上一篇博客中,我们研究了一些视觉效果,在本篇博客中我们将要来讨论一下图层的旋转,平移,缩放,以及可以将扁平物体转换成三维空间对象的CATransform3D。 图层变换 图层的仿射变换 在视图中有一个transform属…...

Linux系统编程——线程基本概念
目录 一,关于多线程 二,重新理解进程 三,线程VS进程 四,线程周边概念 4.1 线程的数据共享 4.2 线程的优点 4.3 线程的缺点 4.4 线程异常 4.5 线程用途 五,一些问题解答 如何理解将资源分配给各个线程&…...

【HALCON】如何实现hw窗口自适应相机拍照成像的大小
前言 在开发一个喷码检测软件的时候碰到相机成像和hw窗体的大小不一致,hw太小显示不完全成像的图片,这使得成像不均匀,现场辨别起来比较不直观,因此需要对其进行一个调整。 解决 省略掉读取图片的环节,我们只需要将…...

【Spring cloud】 认识微服务
文章目录 🍃前言🌴单体架构🎋集群和分布式架构🌲微服务架构🎍微服务带来的挑战⭕总结 🍃前言 本篇文章将从架构的演变过程来简单介绍一下微服务,大致分为一下几个部分 单体架构集群和分布式架…...

一个pdf分割成多个pdf,一个pdf分成多个pdf
在数字化办公和学习中,pdf格式因其良好的兼容性和稳定性而受到广泛欢迎。但有时候,我们可能需要将一个大的pdf文件分割成多个小文件,以便于分享、打印或编辑。今天,我就来教大家几种简单有效的方法,让你轻松实现pdf文件…...

rtsp client c++
直接上代码:源码 void doRtspParse(char *b) {std::vector<std::string> res;char *ptr b, *ptr1 nullptr;while ((ptr1 strstr(ptr, "\r\n"))) {res.push_back(std::string(ptr, ptr1 - ptr));ptr ptr1 2;}int len ptr - b;b[len - 1] \0;…...

实现好友关注功能的Feed流设计
摘要 在社交网络应用中,Feed流是展示好友动态的核心功能。本文将探讨如何设计一个Feed流系统,以实现好友关注和动态展示的功能。 1. Feed流的基本概念 Feed流是用户在社交网络中获取信息的一种方式,通常按照时间顺序展示好友或感兴趣的用户…...

【STM32修改串口波特率】
STM32微控制器中的串口波特率调整通常涉及到USART(通用同步接收器/发送器)模块的配置。USART模块提供了多个寄存器来设置波特率,其中关键的寄存器包括BRR(波特率寄存器)和USART_CR1(控制寄存器1)…...

印章谁在管、谁用了、用在哪?契约锁让您打开手机一看便知
“印章都交给谁在管”、“哪些人能用”、“都有哪些业务在用”…这些既是管理者最关心的印章问题也是影响印章安全的关键要素。但是公司旗下分子公司那么多,各类公章、法人章、财务章、合同章一大堆,想“问”明白很难。 契约锁电子签及印控平台推出“印章…...

[C++初阶]vector的初步理解
一、标准库中的vector类 1.vector的介绍 1. vector是表示可变大小数组的序列容器 , 和数组一样,vector可采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大…...

【等保2.0是什么意思?等保2.0的基本要求有哪些? 】
一、等保2.0是什么意思? 等保2.0又称“网络安全等级保护2.0”体系,它是国家的一项基本国策和基本制度。在1.0版本的基础上,等级保护标准以主动防御为重点,由被动防守转向安全可信,动态感知,以及事前、事中…...

VMware中的三种虚拟网络模式
虚拟机网络模式 1 主机网络环境2 VMware中的三种虚拟网络模式2.1 桥接模式2.2 NAT模式2.3 仅主机模式 3 网络模式选择及配置NAT模式3.1 VMware虚拟网络配置3.2 虚拟机选择网络模式3.3 Windows主机网络配置 4 配置静态IP 虚拟机联网方式为桥接模式,这种模式下&#x…...

深度学习基准模型Transformer
深度学习基准模型Transformer 深度学习基准模型Transformer,最初由Vaswani等人在2017年的论文《Attention is All You Need》中提出,是自然语言处理(NLP)领域的一个里程碑式模型。它在许多序列到序列(seq2seq…...

如何实现公网环境远程连接本地局域网宝塔FTP服务远程管理文件
文章目录 前言1. Linux安装Cpolar2. 创建FTP公网地址3. 宝塔FTP服务设置4. FTP服务远程连接小结 5. 固定FTP公网地址6. 固定FTP地址连接 💡推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。…...

dledger原理源码分析系列(一)-架构,核心组件和rpc组件
简介 dledger是openmessaging的一个组件, raft算法实现,用于分布式日志,本系列分析dledger如何实现raft概念,以及dledger在rocketmq的应用 本系列使用dledger v0.40 本文分析dledger的架构,核心组件;rpc组…...

Github 2024-07-05开源项目日报 Top10
根据Github Trendings的统计,今日(2024-07-05统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6TypeScript项目2Jupyter Notebook项目1Dart项目1C++项目1免费API集合 创建周期:2900 天开发语言:Python协议类型:MIT LicenseSta…...

WHAT - React useEffect 依赖的 Object.is
目录 一、背景二、Object.is 的语法三、Object.is 的行为四、总结 一、背景 在 https://react.dev/reference/react/useEffect 中我们了解到: React will compare each dependency with its previous value using the Object.is comparison. 接下来我们学习一下 Ob…...

【Java EE】Spring IOCDI
Spring IOC & DI 文章目录 Spring IOC & DI一、Spring是什么?二、IOC(控制反转)2.1 通俗理解2.2 造汽车的例子理解IOC2.3 IOC详解1. 获取Bean2. 方法注解——Bean1. 应用场景:2. 应用方法:3. 注意要点: 特别注意: 四、DI4…...

【FreeRTOS】同步互斥与通信 有缺陷的同步示例
目录 1 同步互斥与通信1.1 同步互斥与通信概述1.2 同步与互斥的概念1.3 同步的例子:有缺陷1.4 freertos.c源码3. 互斥的例子:有缺陷4. 通信的例子:有缺陷5. FreeRTOS的解决方案 1 同步互斥与通信 1.1 同步互斥与通信概述 参考《FreeRTOS入门…...

Lambda表达式讲解
简介: Lambda表达式的使用场景非常广泛,主要包括函数式编程、集合操作、排序、线程编程、GUI事件处理、数据处理、Web开发等。 函数式编程:Lambda表达式是函数式编程的重要特性,可以用于替代传统的匿名内部类,简化代码,提高可读性。 集合操作:Lambda表达式可以与集合…...

深入了解Linux中的dnsmasq:配置与优化指南
目录 安装dnsmasqUbuntu/DebianCentOS/RHELFedora 配置dnsmasq基本配置高级配置 启动和测试dnsmasq优化dnsmasq性能优化安全性优化 常见问题与故障排除无法解析域名DHCP分配失败 在Linux系统中, dnsmasq 是一个轻量级的网络服务,主要用于提供DNS缓存和D…...

【React】Ant Design -- Table分页功能实现
实现步骤 为Table组件指定pagination属性来展示分页效果在分页切换事件中获取到筛选表单中选中的数据使用当前页数据修改params参数依赖引起接口重新调用获取最新数据 const pageChange (page) > {// 拿到当前页参数 修改params 引起接口更新setParams({...params,page})…...

400G SR4和800G SR8光模块在AI集群中的应用
人工智能(AI)技术的快速发展下,AI集群的计算能力和数据传输需求不断提升。为了满足这一需求,光模块技术也在不断进步。高速率光模块作为新一代高速光通信解决方案,正在逐步应用于AI集群中,为其提供更高效、…...

ARM功耗管理软件之DVFSAVS
安全之安全(security)博客目录导读 思考:功耗管理软件栈及示例?WFI&WFE?时钟&电源树?DVFS&AVS? 目录 一、ARM功耗管理软件之DVFS 二、ARM功耗管理软件之AVS 一、ARM功耗管理软件之DVFS 有一个实现特定…...

【堆 优先队列】23. 合并 K 个升序链表
本文涉及知识点 堆 优先队列 LeetCode23. 合并 K 个升序链表 给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中,返回合并后的链表。 示例 1: 输入:lists [[1,4,5],[1,3,4],[2,6]] 输出&#…...

云桌面运维工程师
一 深信服驻场工程师 1 深信服AC、AF、AD、NGAF、WOC Atrust、WAF项目实施经验者优先考虑。 负责云桌面POC测试 部署和配置:设置云桌面基础设施,包括虚拟化平台、云桌面管理软件和相关组件。确保正确配置网络、存储和安全设置。 用户体验࿱…...

AGI 之 【Hugging Face】 的【Transformer】的 [ Transformer 架构 ] / [ 编码器 ]的简单整理
AGI 之 【Hugging Face】 的【Transformer】的 [ Transformer 架构 ] / [ 编码器 ]的简单整理 目录 AGI 之 【Hugging Face】 的【Transformer】的 [ Transformer 架构 ] / [ 编码器 ]的简单整理 一、简单介绍 二、Transformer 三、Transformer架构 四、编码器 1、自注意…...