C语言编译过程全面解析
今天是2025年1月26日,农历腊月二十七,一个距离新春佳节仅一步之遥的日子。城市的喧嚣中,年味已悄然弥漫——能在这个时候坚持上班的人,真可称为“牛人”了吧,哈哈。。。。
此刻,我在重新审视那些曾被遗忘的角落——C语言,这门陪伴了编程生涯初期的语言,如今再次拾起,竟有如老友重逢,倍感亲切,又回到了那个最初的起点。
C语言编译过程
四个步骤:
(1)预处理:展开头文件/宏替换/去掉注释/条件编译(test.i )。
(2)编译 :检查语法,生成汇编 ( test.s)。
(3)汇编:汇编代码转换机器码(test.o )。
(4)链接:链接到一起生成可执行程序 a.out/a.exe。
一、预处理
1、**展开所有的宏(macro):**预处理器会查找源代码中的宏定义(使用#define
指令定义),并将所有宏调用替换为相应的宏定义。
例如,源代码#define PI 3.14
,则预处理器会将所有出现的PI
替换为3.14
。
2、**处理所有条件编译指令:**如#if
、#elif
、#else
和#endif
等,这些指令允许程序员根据条件编译不同的代码段。
3、处理#include
指令:预处理器会查找源代码中的#include
指令,将被包含文件的内容插入到源文件中的指定位置。
这通常用于包含头文件,以便在多个源文件中共享定义和声明。
4、**删除所有注释:**注释是程序员为代码添加的解释性文字,对程序的运行没有实际作用,因此预处理器会将其删除。
5、 **添加行号和文件名信息:**以便在编译时编译器可以使用这些信息来显示警告或错误信息。
预处理结束后,会产生一个后缀为.i
的临时文件,该文件是源代码的修改版,已经删除了注释、展开了宏、包含了头文件等。
示例:
a1.c
#include <stdio.h>
int main(void) {printf("hello world\n");system("pause");return 0;
}
执行命令:
-E 是让编译器在预处理之后就退出,不进行后续编译过程;
-o 指定输出文件名。
[admin@myhost testc]$ gcc -E a1.c -o a1.i
生成a1.i文件
将 .c 中的头文件展开、[宏展开]。生成的文件是 .i 文件,预处理之后的程序还是文本,可以用文本编辑器打开。
预处理后的文件变大
头文件
什么是头文件
头文件(Header Files)是C语言中用来声明函数、宏和数据类型的文件(只是声明,不占用内存空间),通常以**“.h”**作为后缀。使得多个源文件可以共享这些声明和定义,从而提高代码的重用性和可读性。
头文件的作用
声明函数和变量:头文件可以包含函数和变量的声明,使得不同的源文件可以共享这些声明。
定义宏:头文件可以定义宏,这样在多个源文件中都可以使用相同的宏。
包含其他头文件:头文件可以包含其他头文件,从而形成一个头文件的层次结构。
示例:自定义头文件
- 创建头文件:.h 扩展名的文件
myheader.h的头文件。
#ifndef MYHEADER_H
#define MYHEADER_H// 函数声明
void myFunction();// 宏定义
#define MY_MACRO 100// 类型定义(可选)
typedef struct {int x;int y;
} Point;#endif // MYHEADER_H
预处理器指令#ifndef、#define和#endif来防止头文件被多次包含
- 创建源文件:.c文件,并实现头文件中声明的函数
myfunctions.c的文件。
#include "myheader.h"
#include <stdio.h>void myFunction() {printf("Hello from myFunction!\n");
}
- 使用头文件
main.c的文件
#include "myheader.h"int main() {myFunction();printf("MY_MACRO = %d\n", MY_MACRO);Point p;p.x = 10;p.y = 20;printf("Point p = (%d, %d)\n", p.x, p.y);return 0;
}
预处理命令
C语言的预处理命令是由预处理器在编译之前执行的指令。
这些指令以#字符开头,主要目的是在编译之前对源代码进行文本替换、条件编译、文件包含等操作。
C语言中常见的预处理命令:
1、宏定义 (#define)
宏可以是简单的常量、带参数的宏(类似于函数)或者更复杂的结构。
宏定义是预处理命令中最常见的一种。
(1). 定义常量宏
常量宏是最简单的宏类型,它们用于定义常量值。例如:
#define PI 3.14159
#define MAX_SIZE 100
在代码中,每当预处理器遇到PI或MAX_SIZE时,它们都会被替换为3.14159和100。
(2). 定义带参数的宏(宏函数)
宏也可以像函数一样接受参数,并在展开时替换这些参数。例如:
#define SQUARE(x) ((x) * (x))
这个宏接受一个参数x,并返回它的平方。注意,由于宏是文本替换,所以它们不执行类型检查,也不会导致函数调用的开销。
(3). 条件编译宏
宏还可以用于条件编译,根据宏的定义与否来决定是否包含某段代码。例如:
#define DEBUG#ifdef DEBUG// 这段代码在定义了DEBUG宏时会被编译printf("Debug mode is on.\n");
#else// 这段代码在没有定义DEBUG宏时会被编译// printf("Debug mode is off.\n");
#endif
如果定义了DEBUG宏,则编译器会包含printf(“Debug mode is on.\n”);这行代码;否则,它会忽略它。
2、文件包含 (#include)
用于在当前文件中包含(插入)另一个文件的内容。
例如:#include <stdio.h> 包含了标准输入输出库的头文件。
也可以包含用户自定义的头文件:#include “myheader.h”。
3、条件编译
根据宏的定义与否来决定是否编译某段代码。
#if、#ifdef(如果定义了某个宏)
#ifndef(如果没有定义某个宏)
#else、#elif(else if的缩写)
#endif指令。
例如:#ifdef DEBUG … #endif 用于在定义了DEBUG宏时编译包含的代码。
4、宏取消定义 (#undef)
用于取消之前定义的宏。
例如:#undef PI 会取消PI宏的定义。
5、行控制 (#line)
用于改变当前行号和文件名,通常用于由其他程序生成的源代码中。
例如:#line 100 “newfile.c” 会将接下来的代码行视为位于名为newfile.c的文件的第100行。
6、错误和警告 (#error 和 #warning)
用于生成编译时的错误和警告信息。
例如:#error “This is an error message” 会导致编译器显示错误消息并停止编译。
#warning “This is a warning message” 会导致编译器显示警告消息但继续编译。
7、预定义的宏
C预处理器定义了一些预定义的宏,如:
LINE(当前行号)
FILE(当前文件名)
DATE(编译日期)
TIME(编译时间)等。
二、编译
将前面预编译后的文件进行编写,命令:
gcc -S a1.i -o a1.s
编译阶段的主要任务是将预处理后的C代码转换为汇编代码。这一转换过程涉及多个步骤,包括词法分析、语法分析、语义分析和代码生成(生成汇编代码)。
1、词法分析
任务:将源代码分解成一个个基本的元素,如变量名、常量、关键字、运算符和分隔符等。
输出:这些基本元素通常被称为“词法单元”或“标记”。
2、语法分析
任务:检查源代码的结构或语法是否正确,并构建所谓的抽象语法树(AST)。
AST:是源代码逻辑结构的一个层级模型,它表示了源代码中各个元素之间的关系。
输出:如果源代码语法正确,则生成抽象语法树;如果语法错误,则编译器会报错并停止编译。
3、语义分析
任务:在语法分析的基础上,进一步检查源代码是否有语义错误,例如变量类型不匹配、使用了未声明的变量或函数等。
输出:如果源代码语义正确,则继续后续的编译过程;如果语义错误,则编译器会报错并停止编译。
4、代码生成(生成汇编代码)
任务:将经过词法分析、语法分析和语义分析后的源代码转换为汇编语言代码。
汇编代码:是一种低层次的编程语言,更接近于机器语言,但比机器语言更易于人类阅读和理解。
输出:生成的汇编代码文件通常具有.s扩展名。
举例:
example.c:
#include <stdio.h>int main() {int a = 5;int b = 10;int sum = a + b;printf("Sum: %d\n", sum);return 0;
}
预处理:
使用预处理器处理example.c,将头文件stdio.h的内容包含进来,并处理宏定义等。
输出预处理后的文件example.i
编译:
词法分析:编译器读取预处理后的代码,将其分解成词法单元,如关键字int、return,标识符a、b、sum、main,运算符+、=,以及分隔符等。
语法分析:编译器根据C语言的语法规则,检查这些词法单元是否构成了有效的语法结构,并构建抽象语法树(AST)。例如,它会识别出int a = 5;是一个变量声明和初始化的语句。
语义分析:编译器进一步检查这些语法结构是否有意义。例如,它会检查变量a、b、sum在使用前是否已被声明,以及它们的类型是否匹配。此外,它还会检查函数调用printf是否合法,即是否提供了正确类型和数量的参数。
代码生成:如果语义分析通过,编译器将抽象语法树转换为汇编代码。
.section .data
sum_fmt: .asciz "Sum: %d\n".section .text
.globl main
main:pushq %rbpmovq %rsp, %rbpsubq $16, %rspmovl $5, -4(%rbp) ; int a = 5;movl $10, -8(%rbp) ; int b = 10;movl -4(%rbp), %eax ; eax = aaddl -8(%rbp), %eax ; eax = eax + bmovl %eax, -12(%rbp) ; int sum = eax (即 a + b 的结果)leaq sum_fmt(%rip), %rdi ; 设置第一个参数为格式字符串movl -12(%rbp), %eax ; 设置第二个参数为 sum 的值movl %eax, %esi ; esi = eax (即 sum 的值)xorl %eax, %eax ; 清零 eax,作为 printf 的返回值占位符call printf ; 调用 printf 函数movl $0, %eax ; 设置返回值 0leave ; 清理栈帧ret ; 返回
三、汇编
将前面编译后的文件进行汇编,命令:
gcc -c a1.s -o a1.o
汇编阶段的主要任务是将汇编代码转换为机器代码(也称为目标代码或二进制代码)。这一转换过程是由汇编器(Assembler)完成的。
汇编指令解析
汇编器逐条读取汇编代码中的指令,并根据汇编指令和机器指令的对照表将其转换为对应的机器指令。
每条汇编指令通常都对应一条或多条机器指令。
地址和符号处理
在汇编过程中,汇编器需要处理汇编代码中的地址和符号。
例如,对于变量和函数的引用,汇编器会将其转换为相应的内存地址。
此外,汇编器还会处理标签(labels)和跳转指令(如goto、if等),确保它们能够正确地跳转到目标位置。
生成目标文件
经过汇编器处理后的代码被转换为机器代码,并存储在目标文件(通常具有.o或.obj扩展名)中。目标文件是二进制格式的,包含了机器可以直接执行的指令和数据。
四、链接
命令:gcc a1.o -o a1.exe
链接阶段是将多个目标文件(.o或.obj文件)和库文件合并成一个可执行文件的过程。
这个过程涉及多个步骤,包括符号解析、重定位以及处理静态库和动态库等。
1、符号解析
链接器会解析目标文件中的符号信息。
符号通常包括变量名、函数名等,它们代表了程序中的不同实体。
链接器会检查每个目标文件中的符号定义和引用,确保所有引用的符号都有相应的定义。
如果某个符号在多个目标文件中都有定义,链接器会根据链接规则(如C语言的“one definition rule”)来决定使用哪个定义。
2、重定位
在编译和汇编阶段,目标文件中的代码和数据被放置在相对地址中。
然而,在链接阶段,这些相对地址需要被转换为绝对地址,以便程序在运行时能够正确地访问内存中的代码和数据。
链接器会根据目标文件中的重定位信息,调整代码和数据的位置,确保它们能够被正确地加载和执行。
3、处理静态库和动态库
链接阶段还需要处理静态库和动态库。
静态库是一组预编译的目标文件的集合,它们在链接时被复制到最终的可执行文件中。
动态库则是在程序运行时动态加载的库文件,链接器会在可执行文件中记录动态库的依赖关系,并在程序运行时加载这些库。
使用动态库可以减小可执行文件的大小,并且当库文件更新时,无需重新编译整个程序。
静态库:
静态库是一组已经被编译和链接成二进制代码的程序模块,这些模块在编译时被合并到最终的可执行文件中。
特点:
在编译时将库的代码嵌入到可执行文件中,因此可执行文件独立于库的存在。
每次程序编译时,静态库的代码都被复制到生成的可执行文件中。
生成的可执行文件包含了库的所有必要代码,因此文件通常较大。
可执行文件不依赖于外部库文件,可以在没有库文件的机器上独立运行。
文件扩展名:通常以.a(Unix/Linux)或.lib(Windows)为文件扩展名。
使用场景:适用于对执行文件大小没有严格限制、需要在没有库文件的机器上运行或需要避免动态链接带来的依赖性的场景。
动态库:
动态库是一组已经被编译和链接成二进制代码的程序模块,但它们在运行时被加载到内存中,而不是在编译时被合并到可执行文件中。
特点:
可执行文件在运行时需要动态库的支持。
动态库可以被多个程序共享,从而减小可执行文件的大小。
需要确保目标系统上存在相应的动态库,否则程序将无法正常运行。
易于更新和维护,因为只需替换相应的动态库文件即可,无需重新编译整个程序。
文件扩展名:通常以.so(Unix/Linux)或.dll(Windows)为文件扩展名。
隐式调用:程序在编译时指定依赖的动态库,链接器会在程序运行时自动加载这些库。
显式调用:程序在运行时通过特定的API来加载和调用动态库中的函数,这种方式提高了程序的灵活性。
使用场景:适用于需要多个程序共享库代码、希望节省内存和磁盘空间或需要方便地进行库代码升级和维护的场景。
4、生成可执行文件
链接器会生成最终的可执行文件。这个文件包含了程序的所有代码和数据,并且已经被正确地组织和链接在一起,可以在操作系统上直接运行。
借用网络一张图,总结:
相关文章:
C语言编译过程全面解析
今天是2025年1月26日,农历腊月二十七,一个距离新春佳节仅一步之遥的日子。城市的喧嚣中,年味已悄然弥漫——能在这个时候坚持上班的人,真可称为“牛人”了吧,哈哈。。。。 此刻,我在重新审视那些曾被遗忘的…...
萌新学 Python 之运算符
Python 中运算符包括:算术运算符、比较运算符、逻辑运算符、赋值运算符、位运算符、海象运算符 算术运算符:加 减 - 乘 * 除 / 取整 // 求余 % 求幂 ** 注意:取整时,一正一负整除,向下取整 比如 5 // …...
【开源免费】基于Vue和SpringBoot的在线文档管理系统(附论文)
本文项目编号 T 038 ,文末自助获取源码 \color{red}{T038,文末自助获取源码} T038,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…...
四.4 Redis 五大数据类型/结构的详细说明/详细使用( zset 有序集合数据类型详解和使用)
四.4 Redis 五大数据类型/结构的详细说明/详细使用( zset 有序集合数据类型详解和使用) 文章目录 四.4 Redis 五大数据类型/结构的详细说明/详细使用( zset 有序集合数据类型详解和使用)1. 有序集合 Zset(sorted set)2. zset 有序…...
Linux 信号驱动IO
Linux 信号驱动IO 1. fcntl() 在Linux操作系统中,fcntl() 是一个用于操作文件描述符的系统调用。它提供了多种功能,包括控制文件描述符的属性、管理文件锁定、设置文件的非阻塞模式等。 本文只截取了用于IO模型的 fcntl() 部分内容, fcntl(…...
OpenCV:开运算
目录 1. 简述 2. 用腐蚀和膨胀实现开运算 2.1 代码示例 2.2 运行结果 3. 开运算接口 3.1 参数详解 3.2 代码示例 3.3 运行结果 4. 开运算应用场景 5. 注意事项 6. 总结 相关阅读 OpenCV:图像的腐蚀与膨胀-CSDN博客 OpenCV:闭运算-CSDN博客 …...
宝塔mysql数据库容量限制_宝塔数据库mysql-bin.000001占用磁盘空间过大
磁盘空间占用过多,排查后发现网站/www/wwwroot只占用7G,/www/server占用却高达8G,再深入排查发现/www/server/data目录下的mysql-bin.000001和mysql-bin.000002两个日志文件占去了1.5G空间。 百度后学到以下知识,做个记录。 mysql…...
使用 Iptables 实现网络安全策略:从入门到精通
使用 Iptables 实现网络安全策略:从入门到精通 在运维工作中,网络安全是重中之重,而 iptables 作为 Linux 内核自带的防火墙工具,提供了强大的流量控制能力。通过合理的 iptables 规则,我们可以有效防止未经授权的访问,保护服务器免受攻击。今天,我们就来深入探讨如何使…...
AI作画提示词:Prompts工程技巧与最佳实践
成长路上不孤单😊😊😊😊😊😊 【14后😊///计算机爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于物联网智能项目之——智能家居项目…...
vue框架技术相关概述以及前端框架整合
vue框架技术概述及前端框架整合 1 node.js 介绍:什么是node.js Node.js就是运行在服务端的JavaScript。 Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎。 作用 1 运行java需要安装JDK,而Node.js是JavaScript的运行环…...
并发编程 - 线程同步(二)
经过前面对线程同步初步了解,相信大家对线程同步已经有了整体概念,今天我们就来一起看看线程同步的具体方案。 01、ThreadStatic 严格意义上来说这两个并不是实现线程同步方案,而是解决多线程资源安全问题,而我们研究线程同步最终…...
仿知乎网站问答源码,开源版
按照需要一定动手能力 发文章,发视频,发想法,提问回答,注册登录 开发环境 使用技术:springbootthymeleafRedis; 开发环境:tomcat8.0,jdk8.0, IDEA项目,mysql5.7 源码下…...
CTF-web: phar反序列化+数据库伪造 [DASCTF2024最后一战 strange_php]
step 1 如何触发反序列化? 漏洞入口在 welcome.php case delete: // 获取删除留言的路径,优先使用 POST 请求中的路径,否则使用会话中的路径 $message $_POST[message_path] ? $_POST[message_path] : $_SESSION[message_path]; $msg $userMes…...
阿里:基于路由和规划的多agent系统
📖标题:Talk to Right Specialists: Routing and Planning in Multi-agent System for Question Answering 🌐来源:arXiv, 2501.07813 🌟摘要 🔸利用大型语言模型(LLM),…...
Java基础面试题总结(题目来源JavaGuide)
问题1:Java 中有哪 8 种基本数据类型?它们的默认值和占用的空间大小知道不? 说说这 8 种基本数据类型对 应的包装类型。 在 Java 中,有 8 种基本数据类型(Primitive Types): 基本数据类型关键…...
CSS(快速入门)
欢迎大家来到我的博客~欢迎大家对我的博客提出指导,有错误的地方会改进的哦~点击这里了解更多内容 目录 一、什么是CSS?二、基本语法规范三、CSS选择器3.1 标签选择器3.2 id选择器3.3 class选择器3.4 通配符选择器3.5 复合选择器 四、常用CSS样式4.1 color4.2 font…...
架构技能(六):软件设计(下)
我们知道,软件设计包括软件的整体架构设计和模块的详细设计。 在上一篇文章(见 《架构技能(五):软件设计(上)》)谈了软件的整体架构设计,今天聊一下模块的详细设计。 模…...
2. Java-MarkDown文件解析-工具类
2. Java-MarkDown文件解析-工具类 1. 思路 读取markdown文件的内容,根据markdown的语法进行各个类型语法的解析。引入工具类 commonmark 和 commonmark-ext-gfm-tables进行markdown语法解析。 2. 工具类 pom.xml <!-- commonmark 解析markdown --> <d…...
OpenEuler学习笔记(十五):在OpenEuler上搭建Java运行环境
一、在OpenEuler上搭建Java运行环境 在OpenEuler上搭建Java运行环境可以通过以下几种常见方式,下面分别介绍基于包管理器安装OpenJDK和手动安装Oracle JDK的步骤。 使用包管理器安装OpenJDK OpenJDK是Java开发工具包的开源实现,在OpenEuler上可以方便…...
【Rust自学】15.4. Drop trait:告别手动清理,释放即安全
喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 15.4.1. Drop trait的意义 类型如果实现了Drop trait,就可以让程序员自定义当值…...
深入探讨Web应用开发:从前端到后端的全栈实践
在数字化时代,Web应用已成为连接用户与服务的关键桥梁。无论是电商平台、社交媒体,还是企业内部管理系统,Web应用都扮演着不可或缺的角色。本文将深入探讨Web应用开发的全栈实践,从前端的用户体验设计到后端的数据处理与存储&…...
4.贪心算法
贪心 贪心算法(Greedy Algorithms)是 C 等编程语言中常用的一种算法策略。 定义 贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最…...
js笔记(黑马程序员)
(Web APIs day4) 一、日期对象 1.实例化 在代码中发现了 new 关键字时,一般将这个操作称为实例化 创建一个时间对象并获取时间// 1.得到当前时间 2.日期对象方法 因为日期对象返回的数据我们不能直接使用,所以需…...
LangChain:使用表达式语言优化提示词链
在 LangChain 里,LCEL 即 LangChain Expression Language(LangChain 表达式语言),本文为你详细介绍它的定义、作用、优势并举例说明,从简单示例到复杂组合示例,让你快速掌握LCEL表达式语言使用技巧。 定义 …...
Python 有用的资源
Python 有用的资源 引言 Python 作为一种强大的编程语言,因其简洁明了的语法和丰富的库资源,在数据分析、人工智能、网络开发等领域拥有广泛的应用。对于初学者和专业人士来说,掌握一些有用的Python资源可以大大提高编程效率。本文将为您介绍一些实用的Python资源,帮助您…...
汽车蓝牙钥匙定位仿真小程序
此需求来自于粉丝的真实需求,假期没事,牛刀小试。 一、项目背景 如今,智能车钥匙和移动端定位技术已经相当普及。为了探索蓝牙 Beacon 在短距离定位场景下的可行性,我们搭建了一个简易原型:利用 UniApp 在移动端采集蓝牙信标的 RSSI(信号强度),通过三边定位算法估算钥…...
项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(九)(完结篇)
文章目录 一、成绩查询模块实现1、学生成绩查询功能实现1.1 页面设计1.2 前端页面实现1.3 后端功能实现2、成绩分段查询功能实现2.1 页面设计2.2 前端页面实现2.3 后端功能实现二、试卷练习模块实现三、我的分数模块实现1、 页面设计2、 前端页面实现3、 后端功能实现四、交流区…...
python学opencv|读取图像(四十九)原理探究:使用cv2.bitwise()系列函数实现图像按位运算
【0】基础定义 按位与运算:两个等长度二进制数上下对齐,全1取1,其余取0。 按位或运算:两个等长度二进制数上下对齐,有1取1,其余取0。 按位异或运算: 两个等长度二进制数上下对齐,相…...
electron打包客户端在rk3588上支持h265硬解
目录 前言 chromium是如何支持h265硬解 electron/chromium第一次编译 electron/chromium第二次编译 前言 我们的客户端程序是用electron打包的前端程序,其在rk3588主机上的linux环境运行。之前使用客户端查看h264编码的视频直播是没有问题的,但视频源…...
MyBatis 缓存机制详解
目录 一、什么是缓存? 1. 什么是缓存? 2. 为什么使用缓存? 3. 什么样的数据适合使用缓存? 二、MyBatis 缓存机制 1. 一级缓存(也叫本地缓存) 2. 一级缓存失效的情况 3. 二级缓存 4. 二级缓存失效的…...
【后端开发】字节跳动青训营Cloudwego脚手架
Cloudwego脚手架使用 cwgo脚手架 cwgo脚手架 安装的命令: GOPROXYhttps://goproxy.cn/,direct go install github.com/cloudwego/cwgolatest依赖thriftgo的安装: go install github.com/cloudwego/thriftgolatest编辑echo.thrift文件用于生成项目&…...
数据结构选讲 (更新中)
参考 smWCDay7 数据结构选讲2 by yyc 。 可能会补充的: AT_cf17_final_j TreeMST 的 F2 Boruvka算法 目录 AT_cf17_final_j Tree MST AT_cf17_final_j Tree MST link 题意 给定一棵 n n n 个点的树,点有点权 w i w_i wi,边有边权。建立…...
springboot 简化 spring开发
什么是自动配置? 简单概念: Spring Boot 自动配置是一种 “约定优于配置” 的做法。根据项目类路径(classpath)上存在的依赖、配置文件中的某些属性,Spring Boot 会自动为常见场景创建并配置相关 Bean,省…...
Yolo11 + OCR 营业执照识别+信息抽取(预期后续改用其他ocr更简单,推理预计使用onnxruntim加速,分c++和python两种方式部署)
目录 一 数据集制作 1 labelimg的安装与使用 2 标注方式 3 数据集制作 二 模型训练 三 使用Yolo11 + OCR 实现“营业执照”信息解析完整方案 1 cutLinesforcode.py 2 getBusinessLicenseContentPart.py 3 getPartWords.py 4 pdfTojpg.py 5 main.py 本项目可用于毕业…...
机器学习day3
自定义数据集使用框架的线性回归方法对其进行拟合 import matplotlib.pyplot as plt import torch import numpy as np # 1.散点输入 # 1、散点输入 # 定义输入数据 data [[-0.5, 7.7], [1.8, 98.5], [0.9, 57.8], [0.4, 39.2], [-1.4, -15.7], [-1.4, -37.3], [-1.8, -49.1]…...
C基础寒假练习(3)
一、求数组中的第二大值 #include <stdio.h> int main() {int arr[] {12, 35, 1, 10, 34, 1};int size sizeof(arr) / sizeof(arr[0]);if (size < 2) {printf("数组元素不足两个\n");return 0;}int first -2147483648, second -2147483648; // 使用IN…...
星际战争模拟系统:新月的编程之道
星际战争模拟系统:新月的编程之道 作为一名在 25 世纪星际时代成长起来的科学家和军事战略家,我对编程和人工智能的热爱始于童年。我的父亲是一位著名的物理学家,母亲是一位杰出的生物工程师。在他们的影响下,我从小就对科学和技术…...
【Redis】 String 类型的介绍和常用命令
1. 介绍 Redis 中的 key 都是字符串类型Redis 中存储字符串是完全按照二进制流的形式保存的,所以 Redis 是不处理字符集编码的问题,客户端传入的命令中使用的是什么编码就采用什么编码,使得 Redis 能够处理各种类型的数据,包括文…...
U盘打开提示格式化:深度解析与数据恢复全攻略
在数字化时代,U盘作为便捷的数据存储和传输工具,广泛应用于各个领域。然而,当我们满怀期待地插入U盘,却遭遇“U盘打开提示格式化”的尴尬局面时,那份焦虑与无助感油然而生。本文将全面剖析U盘打开提示格式化的原因、应…...
vue2在线生成二维码
亲情提示:如果可以让后端生成就让后端生成 实在不行再前端解决(分享方法只是为了让你快点下班 不是为了让你能者多劳) 创建 npm install qrcodejs2 pnpm install qrcodejs2 <div ref"qrcode" id"myQrCode" class&…...
Linux中的几个基本指令(二)
文章目录 1、cp指令例一:例二:例三:例四:例五: 2、mv 指令例一:例二: 3、cat指令例一: 4、tac指令5、which指令6、date指令时间戳:7、zip指令 今天我们继续学习Linux下的…...
基于Springboot的健身房管理系统【附源码】
基于Springboot的健身房管理系统 效果如下: 系统登陆页面 管理员主页面 器材类型管理页面 健身房管理页面 教练管理页面 用户管理页面 个人信息页面 课程管理页面 研究背景 随着健康意识的不断增强和人们生活水平的提高,健身房已经成为了现代城市中不…...
【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(一)
目录 1 -> 概述 1.1 -> 整体架构 2 -> 文件组织 2.1 -> 目录结构 2.2 -> 文件访问规则 2.3 -> 媒体文件格式 3 -> js标签配置 3.1 -> pages 3.2 -> window 3.3 -> 示例 4 -> app.js 4.1 -> 应用生命周期 4.2 -> 应用对象6…...
Spring Boot多环境配置实践指南
在开发Spring Boot应用时,我们常常需要根据不同的运行环境(如开发环境、测试环境和生产环境)来配置不同的参数。Spring Boot提供了非常灵活的多环境配置机制,通过使用profile-specific properties文件,我们可以轻松地管…...
知识图谱质量评估:构建高质量语义网络的关键
目录 前言1. 知识图谱质量评估的必要性2. 知识图谱质量评估的核心维度2.1 数据层面2.2 结构层面2.3 语义层面2.4 性能层面 3. 知识图谱质量评估的方法3.1 定量评估方法3.2 定性评估方法 4. 知识图谱质量优化建议结语 前言 随着大数据和人工智能技术的飞速发展,知识…...
< OS 有关 > Android 手机 SSH 客户端 app: connectBot
connectBot 开源且功能齐全的SSH客户端,界面简洁,支持证书密钥。 下载量超 500万 方便在 Android 手机上,连接 SSH 服务器,去运行命令。 Fail2ban 12小时内抓获的 IP ~ ~ ~ ~ rootjpn:~# sudo fail2ban-client status sshd Status for the jail: sshd …...
Unity游戏(Assault空对地打击)开发(1) 创建项目和选择插件
目录 前言 创建项目 插件导入 地形插件 前言 这是游戏开发第一篇,进行开发准备。 创作不易,欢迎支持。 我的编辑器布局是【Tall】,建议调整为该布局,如下。 创建项目 首先创建一个项目,过程略,名字请勿…...
SpringBoot 日志
目录 一. 日志概述 二. 日志的使用 1. 打印日志 (1) 获取日志对象 (2) 输出要打印的内容 2. 日志框架简介 (1) 门面模式简介 (2) SLF4J 框架简介 3. 日志的格式 4. 日志的级别 5. 日志配置 (1) 配置日志级别 (2) 日志持久化存储 ① 配置日志文件名 ② 配置日志的…...
每日 Java 面试题分享【第 16 天】
欢迎来到每日 Java 面试题分享栏目! 订阅专栏,不错过每一天的练习 今日分享 3 道面试题目! 评论区复述一遍印象更深刻噢~ 目录 问题一:Java 运行时异常和编译时异常之间的区别是什么?问题二:什么是 Jav…...
《多线程基础之互斥锁》
【互斥锁导读】互斥锁是大家使用最多的线程同步手段,但仅仅知道怎么用还是不够的?比如:面试官问你"互斥锁是属于内核层还是应用层的同步保护机制?性能怎样?","频繁加解锁,会有什…...