用函数实现模块化程序设计(适合考研、专升本)

news2025/6/8 6:01:43

函数

定义:本质上是一段可以被连续调用、功能相对独立的程序段

c语言是通过“函数”实现模块化的。根据分类标准不同函数分为以下几类。

  • 用户角度:库函数、自定义函数

  • 函数形式:有参函数、无参函数

  • 作用域:外部函数、内部函数

  • 函数的引入实现了两个目的:1.结构化、模块化编程 2.解决代码重复

  • 函数为什么要先定义后使用:

    通知编译系统函数的返回值类型、函数的名称、函数的参数个数与类型以及函数实现什么功能。
  • 编译系统不检查函数名与形参名同名,即允许函数名与形参名同名。

  • 函数是c语言主要组成部分,是模块化程序设计的思路。

  • 一个c程序由一个或多个源程序文件组成,一个源程序文件对应一个程序模块。一个源程序文件(程序模块)由一个或多个函数及其他有关内容(指令、数据声明与定义等)组成,一个源程序文件是一个编译单位

  • 函数由函数原型函数体构成,函数体由声明部分语句部分构成。声明部分由函数内的变量定义以及对其他函数的声明构成

  • c程序的执行总是从main函数开始的,也是从main函数结束的。

  • 函数返回值的类型应该与函数类型一致若不一致以函数类型为准,即函数类型决定返回值类型

  • 函数间可以相互调用,但不能调用main函数(main只能被操作系统调用

  • 函数通常先定义,再声明,再使用

  • 对于不带返回值的函数,应该定义为void类型,此时函数体内的return语句不应该携带返回值。

  • 函数的形参只能是默认的auto类型,即不能自己加auto或者其它类型

  • c语言规定全局变量只允许使用常量或常量表达式初始化

    #include <stdio.h>
    int a=12,b=13+2;
    int c=a+b;//这里编译报错,因为a、b属于变量
    int main(){}
  • 全局变量不允许与符号常量同名

    #include <stdio.h>
    float A=11.2;//全局变量虽然在符号常量前面,但是会先进行预编译进行宏替换,所以这里实际是 int 1.34=11.2,显然是一个语法错误
    #define A 1.34
    ​
    #define B 100
    int B=100;//全局变量在符号常量后面,这里会产生编译错误,因为这里实际是 int 1.34=11.2,显然是一个语法错误
  • extern一般都是在其他文件中引入本文件的全局变量或函数在其他文件使用,或者扩展本文件全局变量的作用域时才会在本文件使用

  • 默认定义的全局变量与函数是可以在同程序的文件之间共享,只是需要extern声明进来,所以这也是同一程序不同c文件不允许出现同名的外部变量与外部函数

  • 课本要求函数实参的个数、类型必须与形参一致,否则会出现编译错误。但实际中实参的类型可以与形参不一致(地址除外)

函数定义

函数与变量、数组一样,都必须先定义后使用。函数的定义包括:指定函数数据类型(函数的返回值)、指定函数名(函数名反应其功能)、指定形参的类型与名字、完成函数功能。函数定义的目的是为了通知编译系统函数的返回值类型、函数的名称、函数的参数个数与类型以及函数实现什么功能。

格式:

1.定义无参函数:
​
    数据类型 函数名(void){   //形参可以为空也可以写void,表示没有参数
      函数体;
    }
  
  
2.定义有参函数:
​
    数据类型 函数名(形参列表){
      函数体;
    }
  
​
3.定义空函数:
    void 函数名(){
                            //没有函数体
    }
  • 空函数的作用:给以后编写的函数占据一个位置

  • 函数体包括声明部分与语句部分(执行部分)

  • 函数定义时指定的形参不占用存储空间,只有在调用时才分配存储空间

  • 函数定义省略函数的数据类型,此时默认为int类型,但是注意在声明时必须加上int,否则会编译错误

    int main()
    {
        int sum(int,int);//但是声明时必须指定为int
        return 0;
    }
    sum(int sum,int y){//省略了函数数据类型
        return 0;
    }
  • c语言不允许变量名与函数名相同,但是允许形参名与函数名相同(不建议)

     int sum(int sum,int y){
        return 0;
    }
  • 形参与实参可以同名,因为他们的作用域不同,会分配不同的内存空间(不建议)

    int add(int x);//add函数声明
    int x=12;
    add(x);//实参x与形参x同名,但是不影响
  • 函数定义的目的:通知编译系统函数的返回值类型,函数名、函数的参数个数及类型以及函数的功能。

  • c语言函数不允许嵌套定义(在一个函数内定义另一个函数),即所有函数都是平行的。(但是允许嵌套调用

函数声明

格式:

main(){
  add(int x);//add函数声明
  sum(int);//sum函数声明(可以不写参数名)
}
void add(int x){}
void sum(int y){}

作用:告诉计算机次函数在后面已经定义,将函数的作用域提升到声明处,在调用函数检查函数的正确性

  • 函数声明就是函数原型(函数首部)加一个分号即可

  • 函数声明中可以省略参数名而只写参数数据类型,因为函数调用不会检查参数的名字

  • 函数调用时会检查函数类型,函数名,参数类型、个数,顺序必须与函数声明一致

  • 可以将被调函数的声明放在文件开头(所有函数之前)进行声明(又称为外部声明),这样所有函数都可以不在本函数内声明直接调用该函数

    #include <stdio.h>
    int add(int);//add函数声明
    int main(){
        add(1);//调用时可直接调用
    }
    int add(int x){return 0;};//add函数定义
  • 如果被调函数在主调函数上面定义,那么可以不进行函数声明。

     int sum(int x,int y){
        return 0;
    }
    int main()
    {
        int add=sum(2,2);//add函数已经在上面定义,故可不声明直接调用
        printf("%d\n",add);
        return 0;
    }
  • 将一个底部的函数声明到另一个函数内,该函数的作用域只是增加了这一个函数的范围,哪怕中间还有其他函数,也无法调用该函数

在一个函数内调用另一个函数需要满足的条件:
  • 如果是库函数,则需要在开头使用预处理命令对这些库函数引入

  • 如果是自定义函数需要对该函数定义,然后在主调函数中对被调函数作函数声明

函数调用

格式:

函数名(实参列表);//如果是无参函数,则实惨列表为空,但是不能省略括号
  • 实参列表如果是多个使用逗号隔开,无参函数调用实参列表为空,但是不能省略括号

  • 函数调用有3种方式:函数调用语句、函数表达式、函数嵌套调用

    printf("hello!");//函数直接调用
    SUM=sum();//将函数的返回值赋值给一个变量或出现在其他表达式中参加运算
    sum(a,sum());//将返回值作为其他函数参数带入运算
  • 实参可以是常量、变量、表达式

函数调用的过程:
  1. 函数开始调用:为形参分配空间大小,然后将实参的值传递给形参

  2. 函数开始执行:为函数内定义的局部变量分配空间(函数内的static变量已经在编译阶段就开始初始化并分配空间),并对需要调用的其他函数进行声明等,再依次执行其他语句,直到第一个return结束

  3. 函数调用结束:释放本函数内局部变量的空间(函数内的static变量不会被释放),返回主调函数继续执行。

实参与形参之间的数据传递:
  • 形参于实参之间的数据传递也称为虚实结合

  • 实参可以是常量、变量、表达式,调用时实参的数据类型与个数必须与形参一一对应。如果实参的数据类型与形参不一致,则会进行自动类型转换,即把实参数据转换为形参类型再赋值。若实参于形参个数不一致则会出现编译错误。

    int sum(int a);//函数已定义,在这里声明
    SUM=sum(1.34);//将1.34转换为int类型,即1再赋值给形参a
  • 按值传递:形参的改变不会影响实参的值。(数据只能单向由实参—>形参)

    按地址传递:改变形参指向地址的值会改变实参指向地址的值,但改变形参本身的地址值不会改变实参本身的地址值。

    int main(){
      void fn(int *,int *);
      int a=12,b=20,*p=&a;
      fn(p,&b);
      printf("%d\t%d\n",a,*p);
      /*
        输出:10,10(可见在函数中改变指向地址的值会改变外面实参地址的值,但是改变指针本身指向不会改变外面指针的指向)
      */
    }
    void fn(int *p,int *n){
      *p=10;
      p=n;
    }

函数的返回值:
  • return后面的括号可以加也可以不加。例如 return(z)等价于return z。return后面的值可以是一个表达式。例如 return x+y

  • 函数为void类型时函数体内return不应该带返回值。

  • 函数的类型与return不一致时,以函数类型为准,此时数据类型不同会进行自动类型转换。即函数类型决定返回值类型

  • 有数据类型的函数省略return时函数会返回一个不确定的值。

函数的嵌套调用

定义:在一个函数内调用另一个函数

函数的递归调用

定义:函数直接或间接调用自己本身(直接递归调用、间接递归调用

递归调用的条件:

  • 要解决的问题能能简化为一个新问题,这个新问题的解决方法与原解决问题的方法相同--寻找递归表达式

  • 要有一个明确的结束递归条件结束递归调用--寻找递归出口

递归调用分为两个阶段:

  • 递推阶段

  • 回归阶段

数组作函数参数

1.数组元素作函数参数

定义:数组元素只能作函数实参,不能用作形参。数组元素作为实参传值给形参时是按值传递的方式,即数据从实参单向传递给形参。

void fn(int a[2]){}//a[2]是一个具有2个元素数组,而并非数组元素

普通变量与地址做函数参数的不同:
  • 前者按值传递、后者按地址传递

  • 前者分配与实参相应的存储空间、后者只分配第一保存地址的空间

  • 前者不回改变实参的值,后者会改变实参的值。

2.数组名作函数参数

定义:数组名可以做形参也可以做实参,数组名作实参传递的是数组的首地址

  • 数组名在做函数形参时,不管是函数定义还是函数声明,都是作为指针变量处理,调用函数传入的实际上也是地址,而并非整个数组

    int main(){
      int fn(int *a);//a实际是一个指针变量,可以看见声明int *a与下面的函数定义的int a[]等价
        int a[]={12,13,15};
        printf("%d\n",fn(a));//13
        int b=100;
        printf("%d\n",fn(&b));//100(这里也可以看出c系统对数组做形参实际按指针处理,否则这里不能传入变量b的地址)
    }
    int fn(int a[]){
        if(*a==100)return 100;
        return *(++a);//可以看见这里可以对数组名进行指针运算
    }
  • 数组名作函数参数,必须在主调函数与被调函数分别定义数组

    int abc(int arr[]){//被调函数数组arr
      
    }
    int main(){
      int arr2[10]={};//主调函数数组arr2
      abc(arr2);//将arr2作为函数参数传递给abc函数的形参arr
    }
  • 数组做函数参数时实参类型必须与形参类型一致,否则会出现编译错误(普通变量做函数参数两者不同时会进行自动转换)

    即按值传递可以类型不同,会进行自动类型转换。按地址专递传递则必须类型相同。

  • 形参数组如果是一维数组,那么可以省略长度。多维素组只能省略最低维(c编译系统不会检查第1维的大小)

    int arr(int abs[]){}//形参是一维数组,可以参略长度
    int arr(int abs[][2]){}//形参是二维数组,只可参略第一维长度
    int arr(int abs[3][2]){}//与上面等价
    int arr(int abs[4][2]){}//形参数组的第一维在与实参数组相同的情况下,可大于实参数组的第1维,但不能小。例如实参a[2][2]
  • sizeof(形参数组)返回的是实参数组的首地址,也就是首地址指针的sizeof

    #include <stdio.h>
    int aver(int arr[]){
        return sizeof(arr);//实际上是arr数组a[0]的空间大小,是一个指针所以为8
    }
    int main(){
        int arr[10];
        int length=aver(arr);
        printf("%d\n",length);//8
        printf("%d\n",sizeof(arr));//40(arr在本函数中任然属于一个变量,sizeof返回整个数组的空间大小
        printf("%d\n",sizeof(arr[0]));//4(arr第一个元素在本函数中也相当于一个变量,返回4)
        
    }
  • 数组名作为函数实参,函数声明时,不允许值只写数据类型,正确形式为:数据类型 []

    int A=12;
    int main(){
        int add(int[]);//不能是 int add(int)
    }
    int add(int a[]){
        
    }

局部变量与全局变量

任何变量都有作用域,根据作用域不同分为局部变量与全局变量。(数组、函数、指针等其实本质上都等同于变量,其也有作用域)

1.局部变量:函数内定义的变量

分类:在函数内定义、复合语句中定义、函数的形参

  • 函数内定义的局部变量只在本函数内有效

  • 复合语句的局部变量只在复合语句内有效(范围更小)

  • 函数的形参只在本函数内有效

  • 不同函数内的局部变量可以重名互不干扰。同一函数内不同作用域内的函数也可以重名,例如在复合语句定义的变量可以在包含该复合语句的函数中其他位置定义同名变量,在调用时候采取就近原则

  • c语言不允许函数名与变量名相同,但是允许在本函数中定义的局部变量与本函数重名

    int add(){
        int add=20;
        return add;
    }

2.全局变量:函数外定义的变量
  • 全局变量通常可以为本文件中其他所有函数共用,有效范围为定义位置到本源文件结束。(

  • 全局变量的第1个字母通常大写

  • 全局变量与局部变量重名以就近原则调用

  • 默认定义的全局变量不加static的话可以被其他源程序文件调用(但是要使用extern要进行外部声明),所以相关联的多个.c文件的程序中,不同的c文件不允许有同名的全局变量,除非同名的全局变量属于静态外部变量

为什么不建议过多的使用全局变量?
  • 全局变量在整个程序运行期间都占有存储单元

  • 全局变量会使函数的通用性降低

  • 全局变量过多,会降低程序的清晰性

变量的存储方式与生命期

1.存储方式

分类:静态存储、动态存储

  • 全局变量全部采用的静态存储(包括静态局部变量),他们都是在程序开始执行时(编译)就分配固定的内存空间。

  • 局部变量全部采用动态存储,只有在函数调用时分配空间,调用结束后就销毁

⚠️注意:全局变量与静态局部变量都在编译阶段就分配了内存地址,但是全局变量是在编译阶段就进行了初始化,而静态局部变量是在程序运行到该函数时才进行初始化,但是其内存空间是在编译阶段分配好了的。

2.存储类别:

每一个变量(包括数组、函数、指针变量)在定义时都要指定两个属性:数据类型、存储类别。

分类:auto、static、register、extern

⚠️注意:自动变量默认为auto,全局变量默认为extern,其可以在多个文件之间共享,但并非代表其作用域在所有文件,其作用域仍然只限于定义处到本文件结束,其他文件想使用该全局变量需要使用extern声明。换句话说,全局变量在其定义的文件内是全局可见的,但在其他文件中则不是默认可见的。为了在其他文件中使用同一个全局变量,需要使用 extern 关键字来声明该变量,这样编译器就知道在其他地方已经定义了该变量,并且可以在当前文件中访问它。

局部变量的存储类别:
  • static(静态局部变量):使用static关键字声明的局部变量(static变量与全局变量一样在编译开始时就分配了存储单元,直到程序结束。但是static变量的作用域也仅限于本函数内或复合语句内)

  • 对于没有初始化的局部变量,静态局部变量(全局变量也是)系统自动赋初值0、0.0、'\0',而自动变量的值确实不可预知的。

  • register(寄存器变量):为提高执行效率,把局部变量的值放在CPU的寄存器中再进行频繁运算(因为寄存器的存取>内存的存取)

  • auto、static、register属于局部变量的存储类别,一般只能用于局部变量(static还可以放在全局变量前)

全局变量的存储类别:
  • 全局变量的作用域是定义处到源文件结束,这就造成定义之前的函数无法访问该全局变量,可以使用extern做外部变量声明正常引用

    #include <stdio.h>
    int main(){
        extern int A;
        printf("%d\n",A);
    }
    int A=12;

    注意:将一个底部的全局变量外部声明到另一个函数内,该全局变量的作用域只是增加了这一个函数的范围,哪怕中间还有其他函数,也无法访问该全局变量

    #include <stdio.h>
    //extern int A;必须把外部声明放在这里,才能把该全局变量作用域提高到全局,以下所有的函数都可以访问
    int a();//函数声明
    int main(){
        extern int A;//外部声明
        printf("%d\n",A);//12
        // printf("%d\n",a());//这里依然无法访问A,因为上面只是把A声明到本函数内,而a函数没有被声明
    }
    int a(){
        return A;
    }
    int A=12;

    extern 数据类型 变量名可以省略为 external 变量名

    extern int A,B,C 等价于 extern A,B,C
  • 还可以使用extern将全局扩展到其他.c文件

    文件file1.c
    #include <stdio.h>
    int A=12;
    int main(){
    ​
    }
    ​
    文件file2.c
    extern A;//此时在file2中可以访问到A
    int main(){
    ​
    }
    ​
    ⚠️注意:使用 extern 关键字在其他文件中声明全局变量时,不会为该变量分配新的内存空间,而是告诉编译器该变量已经在其他地方定义了。
  • 还可以使用static将全局变量限制在本文件中,其他文件不允许访问(静态外部变量)

    文件file1.c
    #include <stdio.h>
    static int A=12;
    int main(){
    ​
    }
    ​
    文件file2.c
    extern A;//因为A被限制在file1.c中,所以这里的声明无效
    int main(){
    ​
    }

声明全局变量的存储类型于声明局部变量的存储类型的区别:
  1. 对于局部变量使用auto、static、register声明的局部变量是为了指定变量的存储区域与生存期

  2. 对于全局变量使用extern与static是为了扩展或限制全局变量的作用域

内部函数与外部函数

内部函数:

定义:函数只能被本文件中的其他函数调用

格式:

static 数据类型 函数名(参数列表);  例如 static add(int a){}

外部函数:

定义:函数可以被其他文件中的函数调用

格式:

extern 数据类型 函数名(参数列表);  例如 extern add(int a);//声明函数已外部定义
  • 定义函数时省略存储类别函数默认是外部函数

  • 不加static定义的函数都属于外部函数,所以多个c文件的程序在连接时,不允许出现同名的函数,否则会产生重复定义,除非同名的函数是内部函数

  • 若要调用其他文件的函数,与变量一样,需要使用extern将函数声明到本文件中

总结:不管是全局的变量、数组、还是函数,都可以使用extern和static对作用域进行扩展或限制,而对于局部的变量、数组、函数来说使用auto、static等只是改变其存储类型。

#include <stdio.h>
extern int ARR[12];
// int a();//函数声明
int main(){
    extern int a();//与上面的函数声明等价
    printf("%d\n",a());//12
    printf("%d\n",ARR[0]);//1
}
int a(){
    return 12;
}
int ARR[12]={1};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2403793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字符串字典序最大后缀问题详解

字符串字典序最大后缀问题详解 一、问题定义与背景1.1 问题描述1.2 实际应用场景 二、暴力解法及其局限性2.1 暴力解法思路2.2 代码示例2.3 局限性分析 三、双指针算法&#xff1a;高效解决方案3.1 算法核心思想3.2 算法步骤3.3 代码实现3.4 与暴力解法对比 四、复杂度分析4.1 …

VScode打开后一直显示正在重新激活终端 问题的解决方法

一、问题 本人打开“.py”文件后&#xff0c;同时会出现以下两个问题。 1、VScode一直循环在”正在重新激活终端“ 2、日志显示intellicode报错&#xff1a; Sorry, something went wrong activating IntelliCode support for Python. Please check the “Python” and “VS I…

pe文件结构(TLS)

TLS 什么是TLS? TLS是 Thread Local Storage 的缩写&#xff0c;线程局部存储。主要是为了解决多线程中变量同步的问题 如果需要要一个线程内部的各个函数调用都能访问&#xff0c;但其它线程不能访问的变量&#xff08;被称为static memory local to a thread 线程局部静态变…

中型零售业数据库抉择:MySQL省成本,SQL SERVER?

针对中型零售企业&#xff08;20台固定POS数十台移动POS&#xff0c;含库存管理与结算业务&#xff09;的操作系统与数据库选型&#xff0c;需平衡性能、成本、扩展性及运维效率。结合行业实践与系统需求&#xff0c;建议如下&#xff1a; &#x1f5a5;️ ​​一、操作系统选型…

IDEA中的debug使用技巧

详细教学视频见b站链接&#xff1a;IDEA的debug调试 CSDN详细博客文章链接&#xff1a;debug文章学习 以下为个人学习记录总结&#xff1a; idea中的debug模式界面如下&#xff1a; 现在详细介绍图标作用&#xff1a; 图标一&#xff08;Show Execution Point&#xff09;&…

RockyLinux9.6搭建k8s集群

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

AI IDE 正式上线!通义灵码开箱即用

近期&#xff0c;通义灵码AI IDE正式上线&#xff0c;即日起用户可在通义灵码官网免费下载开箱即用。 作为AI原生的开发环境工具&#xff0c;通义灵码AI IDE深度适配了最新的千问3大模型&#xff0c;并全面集成通义灵码插件能力&#xff0c;具备编程智能体、行间建议预测、行间…

Ubuntu20.04基础配置安装——系统安装(一)

引言&#xff1a; 工作需要&#xff0c;Ubuntu的各类环境配置&#xff0c;从23年开始使用Ubuntu20.04之后&#xff0c;尽管能力在不断提升&#xff0c;但是依旧会遇到Ubuntu系统崩掉的情况&#xff0c;为了方便后续系统出现问题及时替换&#xff0c;减少从网上搜索资源进行基础…

Kafka入门-消费者

消费者 Kafka消费方式&#xff1a;采用pull&#xff08;拉&#xff09;的方式&#xff0c;消费者从broker中主动拉去数据。使用pull的好处就是消费者可以根据自身需求&#xff0c;进行拉取数据&#xff0c;但是坏处就是如果Kafka没有数据&#xff0c;那么消费者可能会陷入循环…

中电金信:从智能应用到全栈AI,大模型如何重构金融业务价值链?

导语 当前&#xff0c;AI大模型技术正加速重构金融行业的智能化图景。为助力金融机构精准把握这一变革机遇&#xff0c;中电金信与IDC联合发布《中国金融大模型发展白皮书》。《白皮书》在梳理了AI大模型整体发展现状的基础上&#xff0c;结合金融行业用户的需求调研深入分析了…

巴西医疗巨头尤迈Kafka数据泄露事件的全过程分析与AI安防策略分析

一、事件背景与主体信息 涉事主体:Unimed,全球最大医疗合作社,巴西医疗行业龙头企业,拥有约1500万客户。技术背景:泄露源于其未保护的Kafka实例(开源实时数据传输平台),用于客户与聊天机器人“Sara”及医生的实时通信。二、时间线梳理 时间节点关键事件描述2025年3月24…

快速上手 Metabase:从安装到高级功能实战

文章目录 1. 引言&#xff1a;Metabase——轻量级的数据分析工具&#x1f3af; 学完本教程你能掌握&#xff1a; 2. 安装 Metabase&#xff1a;本地部署实操2.1 环境准备2.2 使用 Docker 安装 Metabase2.3 初始化设置2.4 连接外部数据库 3. 第一个数据探索&#xff1a;5分钟创建…

Linux基础命令which 和 find 简明指南

&#x1f3af; Linux which 和 find 命令简明指南&#xff1a;从入门到实用 &#x1f4c5; 更新时间&#xff1a;2025年6月7日 &#x1f3f7;️ 标签&#xff1a;Linux | which | find | 命令行 | 文件查找 文章目录 前言&#x1f31f; 一、Linux 命令的本质与 which、find 的作…

思尔芯携手Andes晶心科技,加速先进RISC-V 芯片开发

在RISC-V生态快速发展和应用场景不断拓展的背景下&#xff0c;芯片设计正面临前所未有的复杂度挑战。近日&#xff0c;RISC-V处理器核领先厂商Andes晶心科技与思尔芯&#xff08;S2C&#xff09;达成重要合作&#xff0c;其双核单集群AX45MPV处理器已在思尔芯最新一代原型验证系…

kafka消息积压排查

kafka监控搭建&#xff1a;https://insights.blog.csdn.net/article/details/139129552?spm1001.2101.3001.6650.1&utm_mediumdistribute.pc_relevant.none-task-blog-2%7Edefault%7Ebaidujs_baidulandingword%7EPaidSort-1-139129552-blog-132216491.235%5Ev43%5Econtrol…

drawio 开源免费的流程图绘制

开源地址 docker-compose 一键启动 #This compose file adds draw.io to your stack version: 3.5 services:drawio:image: jgraph/drawiocontainer_name: drawiorestart: unless-stoppedports:- 8081:8080- 8443:8443environment:PUBLIC_DNS: domainORGANISATION_UNIT: unitOR…

YOLOv8 升级之路:主干网络嵌入 SCINet,优化黑暗环境目标检测

文章目录 引言1. 低照度图像检测的挑战1.1 低照度环境对目标检测的影响1.2 传统解决方案的局限性 2. SCINet网络原理2.1 SCINet核心思想2.2 网络架构 3. YOLOv8与SCINet的集成方案3.1 总体架构设计3.2 关键集成代码3.3 训练策略 4. 实验结果与分析4.1 实验设置4.2 性能对比4.3 …

传输层:udp与tcp协议

目录 再谈端口号 端口号范围划分 认识知名端口号(Well-Know Port Number) 两个问题 netstat pidof 如何学习下三层协议 UDP协议 UDP协议端格式 UDP的特点 面向数据报 UDP的缓冲区 UDP使用注意事项 基于UDP的应用层协议 TCP协议 TCP协议段格式 1.源端口号…

centos7.9源码安装zabbix7.12,求赞

centos7.9源码安装zabbix7.12-全网独有 3.CentOS7_Zabbix7.0LTS3.1.安装环境3.2.换成阿里源3.3.安装相关依赖包3.3.1.直接安装依赖3.3.2.编译安装-遇到问题01-net-snmp3.3.3.编译安装-遇到问题02-libevent3.3.4.编译安装-遇到问题03-安装openssl 3.4.创建用户和组3.5.下载上传源…

亚远景科技助力东风日产通过ASPICE CL2评估

热烈祝贺东风日产通过ASPICE CL2评估 近日&#xff0c;东风日产PK1B VCM热管理项目成功通过ASPICE CL2级能力评估&#xff0c;标志着东风日产在汽车电子软件研发管理体系及技术创新能力上已达到国际领先水平&#xff0c;为其全球化布局注入强劲动能。 ASPICE&#xff1a;国际竞…