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

函数

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

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);//但是声明时必须指定为intreturn 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));//13int 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]={};//主调函数数组arr2abc(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);//8printf("%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());//12printf("%d\n",ARR[0]);//1
}
int a(){return 12;
}
int ARR[12]={1};

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

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

相关文章

OpenCV 滑动条调整图像亮度

一、知识点 1、int createTrackbar(const String & trackbarname, const String & winname, int * value, int count, TrackbarCallback onChange 0, void * userdata 0); (1)、创建一个滑动条并将其附在指定窗口上。 (2)、参数说明: trackbarname: 创建的…

vcs仿真产生fsdb波形的两种方式

目录 方法一&#xff1a; 使用verilog自带的系统函数 方法二&#xff1a; 使用UCLI command 2.1 需要了解什么是vcs的ucli&#xff0c;怎么使用ucli&#xff1f; 2.2 使用ucli dump波形的方法 使用vcs仿真产生fsdb波形有两种方式&#xff0c;本文参考《vcs user guide 20…

【前端】每日一道面试题6:解释Promise.any和Promise.allSettled的使用场景及区别。

Promise.any() 和 Promise.allSettled() 是 JavaScript 中用于处理异步操作的两种不同策略的 Promise 组合器&#xff0c;它们的核心区别在于逻辑目标与结果处理方式&#xff1a; 1. Promise.any() 使用场景&#xff1a; 需要获取 首个成功结果&#xff08;类似竞速成功优先&…

数据链路层__

文章目录 数据链路层基本概念&#xff08;1&#xff09;链路管理&#xff1a;面向连接的服务&#xff08;2&#xff09;帧同步&#xff1a;成帧1、字符计数法2、字符填充法&#xff08;带填充的首尾界符法&#xff09;3、带填充的首位标志法4、物理层编码违例法 &#xff08;3&…

coze智能体后端接入问题:

是否一定要按照coze官方API文档格式调用&#xff1f; 不一定&#xff1a;以下面代码为例(给了注释) app.route(/compare_models, methods[POST]) def compare_models():print("收到 compare_models 请求&#xff01;") #begin-这一部分代码作用&#xff1a;从前端接…

如何轻松、安全地管理密码(新手指南)

很多人会为所有账户使用相同、易记的密码&#xff0c;而且常常多年不换。虽然这样方便记忆&#xff0c;但安全性非常低。 您可能听说过一些大型网站的信息泄露事件&#xff0c;同样的风险也可能存在于您的WordPress网站中。如果有不法分子获取了访问权限&#xff0c;您的网站和…

宝塔think PHP8 安装使用FFmpeg 视频上传

宝塔think PHP8 安装使用FFmpeg 一、 安装think PHP8二、安装 FFmpeg1&#xff0c;登录到宝塔面板。2&#xff0c;进入“软件商店”。3&#xff0c;搜索“FFmpeg”。4&#xff0c;选择版本点击安装。5&#xff0c;检查 FFmpeg 是否安装成功6&#xff0c; 在 ThinkPHP 8 中使用 …

Android 轻松实现 增强版灵活的 滑动式表格视图

表格视图组件&#xff0c;支持&#xff1a; 1. 无标题模式&#xff1a;只有数据行也可以正常滑动 2. 两种滑动模式&#xff1a;固定第一列 或 全部滑动 3. 全面的样式自定义能力 4. 智能列宽计算 1. 无标题模式支持 设置无标题&#xff1a;调用 setHeaderData(null) 或 …

【Python进阶】元类编程

目录 &#x1f31f; 前言&#x1f3d7;️ 技术背景与价值&#x1fa79; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f9e0; 一、技术原理剖析&#x1f4ca; 核心概念图解&#x1f4a1; 核心作用讲解&#x1f527; 关键技术模块说明⚖️ 技术选…

DeepSeek模型性能优化:从推理加速到资源调度的全栈实践

引言 在生产环境中部署DeepSeek模型时,性能优化直接关系到服务质量和运营成本。本文将深入探讨从芯片级优化到分布式调度的全栈性能提升方案,涵盖计算图优化、内存管理、批处理策略等关键技术,并分享在千万级QPS场景下的实战经验,帮助工程团队突破性能瓶颈,实现成本与效能…

Ctrl+R 运行xxx.exe,发现有如下问题.

CtrlR 运行xxx.exe,发现有如下问题. (1)找不到Qt5Core.all,Qt5Cored.dll,Qt5Gui.dll,Qt5Guid.dll,Qt5Widgets.all,Qt5Widgetsd.dll? (2)之后找不到libwinpthread-1.dll 从这个目录拷贝相应的库到运行xx.exe目录下 方法二:将库路径添加到系统PATH环境变量里: 在Path中添加路…

硅基计划2.0 学习总结 陆 抽象类与接口

文章目录 一、抽象类1. 定义2. 示例代码3. 特性 二、接口初识1. 定义2. 命名与语法3. 示例代码4. 常见特性5. 多接口实现6. 接口的继承 三、Object类初识1. equals方法2. hascode方法 一、抽象类 1. 定义 请你假设这样一个场景&#xff0c;我们定义一个人的类&#xff0c;这个…

Linux命令基础(2)

su和exit命令 可以通过su命令切换到root账户 语法&#xff1a;su [-] 用户名 -符号是可选的&#xff0c;表示是否在切换用户后加载环境变量&#xff0c;建议带上 参数&#xff1a;用户名&#xff0c;表示要切换的用户&#xff0c;用户名可以省略&#xff0c;省略表示切换到ro…

C++算法训练营 Day10 栈与队列(1)

1.用栈实现队列 LeetCode&#xff1a;232.用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x)将元素x推到队列的末尾 int pop(…

设计模式域——软件设计模式全集

摘要 软件设计模式是软件工程领域中经过验证的、可复用的解决方案&#xff0c;旨在解决常见的软件设计问题。它们是软件开发经验的总结&#xff0c;能够帮助开发人员在设计阶段快速找到合适的解决方案&#xff0c;提高代码的可维护性、可扩展性和可复用性。设计模式主要分为三…

【QT】自定义QWidget标题栏,可拖拽(拖拽时窗体变为normal大小),可最小/大化、关闭(图文详情)

目录 0.背景 1.详细实现 思路简介 .h文件 .cpp文件 0.背景 Qt Linux&#xff1b;项目遇到问题&#xff0c;解决后特此记录 项目需要&#xff0c;个性化的标题栏&#xff08;是个widget&#xff09;&#xff0c;在传统的三个按钮&#xff08;最大化、最小化、关闭&#xf…

如何用 pnpm patch 给 element-plus 打补丁修复线上 bug(以 2.4.4 修复 PR#15197 为例)

背景 在实际项目开发中&#xff0c;依赖的三方库&#xff08;如 element-plus&#xff09;难免会遇到 bug。有时候官方虽然已经修复&#xff0c;但新版本升级成本高&#xff0c;或者有兼容性风险。这时&#xff0c;给依赖打补丁是最优雅的解决方案之一。 本文以 element-plus…

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…

优化电脑的磁盘和驱动器提高电脑性能和延长硬盘寿命?

磁盘优化 磁盘清理&#xff1a; 使用系统自带的磁盘清理工具&#xff08;如Windows的“磁盘清理”&#xff09;删除不必要的文件。清空回收站。删除临时文件和缓存。 磁盘碎片整理&#xff08;针对机械硬盘&#xff09;&#xff1a; 定期进行磁盘碎片整理&#xff0c;以提高文…

EDA断供危机下的冷思考:中国芯片设计软件的破局之道优雅草卓伊凡

EDA断供危机下的冷思考&#xff1a;中国芯片设计软件的破局之道优雅草卓伊凡 一、EDA是什么&#xff1f;芯片行业的”隐形基石” 1.1 EDA技术解析 EDA&#xff08;Electronic Design Automation&#xff0c;电子设计自动化&#xff09;是用于设计和验证集成电路的软件工具链…