编译原理——词法分析
文章目录
- 词法分析:从基础到自动构造
- 一、词法分析程序的设计
- 一、词法分析程序的设计
- 二、PL/0编译程序中词法分析程序的设计与实现
- 1. 语法特定考量
- 2. 通过状态转移表运用有限状态自动机
- 3. 示例代码片段(用于说明的伪代码)
- 三、单词的形式化描述工具
- 1. 正则表达式剖析
- 2. 在描述不同单词类型中的应用
- 3. 与其他形式化描述工具的比较
- 四、有穷自动机
- (一)确定的有穷自动机DFA
- (二)不确定的有穷自动机NFA
- (三)NFA转换为等价的DFA
- (四)确定有穷自动机的化简
- 五、正规式与有穷自动机的等价性
- 六、正规文法与有穷自动机的等价性
- 七、词法分析程序的自动构造工具
- (一)lex描述文件中使用的正规表达式
- (二)lex描述文件的格式
- (三)lex的使用
- (四)与yacc的接口约定
词法分析:从基础到自动构造
在编译原理的世界里,词法分析作为编译的第一个阶段,承担着将输入的源程序分割成一个个单词单元的重要任务。它就像是一位勤劳的 “分拣员”,把杂乱无章的字符流整理成有意义的单词序列,为后续的语法分析等工作奠定基础。
当源程序的字符流输入到词法分析器中,词法分析器会按照预先设定的规则,对字符逐一进行检查和识别。比如,对于一段简单的 C 语言代码 “int num = 10;”,词法分析器会将其分割为 “int”(关键字)、“num”(标识符)、“=”(运算符)、“10”(常量)和 “;”(界符)这些单词单元。这种将无结构的字符流转化为有结构的单词序列的操作,就如同把一堆杂乱的零件分类整理成一个个可识别的部件,为后续的语法分析提供了有序且易于处理的输入。
一、词法分析程序的设计
很抱歉给你带来了困扰,可能是出现了一些误解,并非有意将内容改为英文。我将立刻把这部分内容重新翻译回中文,并且会依据你最初对内容丰富、添加表格的要求,进一步优化完善。
一、词法分析程序的设计
设计一个词法分析程序,就如同构建一个复杂且精密的机械装置。明确其输入与输出,是构建这个装置的基石。输入的源程序字符流,可被视作一条源源不断的原材料输送带。每个字符就像一个个无序的小零件,依次流入词法分析这个庞大而忙碌的“生产车间”。而输出则是一个个被精准识别的单词,这些单词就像是经过精心预处理的标准化组件,具备特定功能和确切含义。它们整齐排列,急切地等待进入下一个关键阶段——语法分析。
在整个设计过程中,字符扫描方式的选择起着决定性作用。业界通常采用从左至右逐个字符扫描的经典策略。这类似于我们自幼养成的从左至右阅读单词和句子的习惯,既自然又符合大多数人的思维模式。实际上,除了从左至右逐个字符扫描的方法外,还有其他扫描方式,每种方式都有其优缺点,具体如表1:字符扫描方式对比 所示。
扫描方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
从左至右逐个字符扫描 | 简单直观、易于实现,符合人类阅读习惯 | 对某些复杂语言结构的识别效率较低 | 大多数常见编程语言 |
从右至左逐个字符扫描 | 在处理诸如后缀表达式等特定语言结构时具有优势 | 不符合常规阅读习惯,实现起来相对复杂 | 特定领域语言,如逆波兰表示法语言 |
块扫描(例如按固定长度的单词块扫描) | 当字符流规律性较强时,扫描速度快 | 灵活性差,难以适应单词长度多变的语言 | 一些标记语言,如某些简单的配置文件语言 |
如何准确识别不同类型的单词,如关键字、标识符、运算符和常量等,无疑是词法分析程序设计的核心与关键任务。一般来说,会巧妙运用状态转换的思想。通过状态之间的动态转移,能够准确确定当前所识别单词的类型。不同类型单词的识别复杂度也有所不同,详见表2:单词类型识别复杂度分析 。
单词类型 | 识别复杂度 | 主要影响因素 |
---|---|---|
关键字 | 低 | 它们来自预定义的固定集合,精确匹配即可 |
标识符 | 中 | 需要根据字符组合规则进行判断,状态转移相对复杂 |
运算符 | 低 | 特定符号对应特定运算符,易于识别 |
常量 | 中(数字常量低,字符串常量相对较高) | 数字常量格式相对固定,而字符串常量需要处理引号及内部字符 |
以关键字“int”的识别为例,当从状态S0扫描到字符‘i’时,会进入专门用于识别关键字“int”的中间状态S3。如果紧接着扫描到字符‘n’,就会进入状态S4,再扫描到字符‘t’时,关键字“int”就被成功识别,进入最终状态S5。这种状态转移的差异,生动地体现了不同类型单词识别过程的独特性。不同编程语言在各类单词的定义和识别方式上也存在显著差异。以关键字为例,我们进一步扩充表3:常见编程语言关键字对比 。
编程语言 | 部分关键字示例 | 关键字识别特点 | 关键字功能简述 | 关键字数量(大致范围) | 与新特性相关的关键字(示例) |
---|---|---|---|---|---|
C | int、if、while、return | 关键字集合相对固定,词法分析器通过精确匹配进行识别 | 用于定义变量类型、流程控制、函数返回等 | 约32个 | _Bool(C99中引入,用于定义布尔类型) |
Python | if、else、for、def、class | 区分大小写,严格匹配预定义的关键字集合 | 实现条件判断、循环控制、函数定义、类定义等 | 约35个 | async、await(Python 3.5中引入,用于异步编程) |
Java | class、public、private、static、void | 关键字具有明确的语法和语义功能,词法分析时精确匹配 | 构建类、设置访问权限、定义静态成员、声明方法返回类型等 | 约50个 | var(Java 10中引入,用于局部变量类型推断) |
JavaScript | var、function、let、const、async | 关键字集合可能随版本更新而变化,需要准确识别 | 变量声明、函数定义、块作用域变量声明、常量声明、异步函数定义等 | 约49个 | yield(用于生成器函数) |
C++ | int、double、if、else、while、class、template | 关键字集合丰富且复杂,采用精确匹配进行识别 | 数据类型定义、流程控制、类定义、模板编程等 | 约96个 | concept(C++20中引入,用于概念定义,增强模板编程) |
为了更清晰、全面地阐述不同单词类型在一般情况下的识别规则,我们参考表4:通用单词类型识别规则 。
单词类型 | 示例 | 识别规则 | 在程序中的作用 | 与其他单词类型的关联(示例) |
---|---|---|---|---|
关键字 | int、while等 | 预定义的固定字符串集合,词法分析器通过精确匹配进行识别 | 作为编程语言的语法基石,引导程序的结构和逻辑走向。例如,“if”用于条件判断的开头 | 与标识符结合。例如,在“int num;”中,“int”定义了“num”的类型 |
标识符 | num、count等 | 以字母开头,后跟字母或数字的字符串,如上述通过状态转移进行识别 | 为变量、函数、类等程序元素命名,便于在程序中引用和操作。例如,“count”可作为计数变量名 | 用作函数参数、返回值等,并与运算符和常量一起参与表达式运算 |
运算符 | +、-、*、/等 | 根据运算符的特定符号进行识别 | 执行各种数学、逻辑或其他操作。例如,“+”用于加法运算 | 连接标识符和常量以构建表达式,如“num + 10” |
常量 | 10、3.14、"hello"等 | 数字常量根据数字格式进行识别,字符串常量识别为用引号括起来的字符序列 | 表示固定值,为程序提供数据支持。例如,“3.14”可用于数学计算中的圆周率近似值 | 作为表达式中的操作数,与运算符和标识符协同工作 |
我将把内容完整翻译成中文,同时进一步优化表述,结合具体案例让阐述更清晰。
二、PL/0编译程序中词法分析程序的设计与实现
PL/0是一种简单且易于理解的编程语言,其编译程序里的词法分析程序设计独具特色。在实现过程中,必须依据PL/0语言的语法规则构建词法分析逻辑。
1. 语法特定考量
- 关键字识别:PL/0有一组预先定义好的关键字,比如“begin”“end”“if”“then”“while”“do”等。这些关键字在定义PL/0的控制流和程序结构方面起着关键作用。例如,“if - then”结构用于条件执行。词法分析程序需要极为准确地识别这些关键字。它通常通过维护一个关键字表来实现这一点。在扫描源代码时,对于每个类似单词的标记,它会检查该标记是否与关键字表中的任何条目匹配。如果匹配,就赋予相应的关键字类型。
- 标识符命名规则:PL/0中的标识符遵循特定规则。它们必须以字母开头,后面可以跟一系列字母和数字。例如,“count”“sumValue”“userInput”都是有效的标识符。为了处理标识符识别,词法分析程序采用基于状态的方法。当它首次遇到一个字母时,就进入“标识符构建”状态。只要后续字符是字母或数字,它就保持在这个状态。一旦遇到非字母数字字符,该标识符就被视为完成,并将其类型标记为标识符。
- 常量表示:PL/0支持整数常量和字符串常量。整数常量就是简单的数字序列,像“10”“256”或“ - 15”。字符串常量用单引号括起来,例如’Hello, PL/0!’ 。在处理整数常量时,词法分析程序在扫描时只需累加数字。对于字符串常量,当遇到单引号时,它就进入“字符串起始”状态,然后持续收集字符,直到遇到结束的单引号。
2. 通过状态转移表运用有限状态自动机
- 状态转移表构建:状态转移表是PL/0词法分析程序设计中的一个基础工具。该表由代表不同状态的行和代表可能输入字符的列组成。例如,在初始状态(我们称其为S0)下,如果遇到字母字符,程序就转移到“标识符构建”状态(比如S1)。在S1状态下,如果扫描到另一个字母或数字,它就保持在S1。但如果检测到非字母数字字符,它就转移到“标识符后”状态(S2)。
- 对于关键字识别,当处于初始状态S0且扫描到关键字起始字符(比如“begin”的’b’)时,它可能转移到特定于该关键字的中间状态。例如,从S0开始,扫描到’b’后,转移到S3。接着,如果扫描到下一个字符’e’,就移动到S4,以此类推,直到在该关键字的最终状态中识别出整个“begin”。
- 在处理常量时,从S0开始,如果扫描到数字用于整数常量,它就进入“整数构建”状态(S5)。在S5中,后续数字使它保持在同一状态,当遇到非数字字符时,整数常量就完成了。对于字符串常量,从S0开始,当扫描到单引号时,它进入“字符串起始”状态(S6),并在一系列状态中持续收集字符,直到找到结束的单引号。
- 高效词法分析:通过基于有限状态自动机原理使用这个状态转移表,PL/0词法分析程序能够高效地逐个字符处理源代码。它能快速确定字符流中每个标记的类型。例如,考虑PL/0源代码“begin if x > 10 then y := 20; end”。词法分析程序从S0开始,扫描到“begin”,识别出它是一个关键字,接着移动到“if”,这也是一个关键字。当扫描到“x”时,它进入标识符构建状态,当遇到“>”符号时,识别出它是一个运算符。这个过程持续进行,将整个字符流转换为符合PL/0语言规则的标记序列。
3. 示例代码片段(用于说明的伪代码)
下面是一个简单的伪代码示例,展示如何为PL/0实现基于状态的词法分析:
currentState = S0
inputIndex = 0
inputString = "begin if x > 10 then y := 20; end"while inputIndex < inputString.length:currentChar = inputString[inputIndex]if currentState == S0:if currentChar.isalpha():currentState = S1token = currentCharelif currentChar in keywordStarters:currentState = getKeywordStartState(currentChar)token = currentCharelif currentChar.isdigit():currentState = S5token = currentCharelif currentChar == '\'':currentState = S6token = currentCharelse:# 处理其他字符,如运算符、标点符号identifyOperatorOrPunctuation(currentChar)elif currentState == S1:if currentChar.isalnum():token += currentCharelse:if token in keywordTable:print(token + " 是一个关键字")else:print(token + " 是一个标识符")currentState = S0# 像之前一样处理当前非字母数字字符if currentChar.isdigit():currentState = S5token = currentCharelif currentChar == '\'':currentState = S6token = currentCharelse:identifyOperatorOrPunctuation(currentChar)# 对于其他状态,如S5(整数构建)、S6(字符串构建)等,有类似逻辑inputIndex += 1
总的来说,PL/0编译器中词法分析程序的设计与实现是一个精心构建的过程,充分考虑了该语言的特定语法规则。通过借助有限状态自动机的状态转移表,并遵循系统的标记识别方法,它有效地将PL/0源代码的字符流转换为有意义的标记序列,为编译过程的后续阶段奠定了基础。
三、单词的形式化描述工具
在编程语言处理这个复杂的领域中,精确界定单词的构成规则至关重要。为了实现这一点,形式化描述工具便派上了用场。其中,正则表达式是一种强大且应用广泛的工具。
1. 正则表达式剖析
正则表达式运用一组特定的运算符和操作数来描述单词模式。这些运算符赋予了正则表达式精确描述各种单词结构的灵活性。
- 基础运算符
- 连接:这是最基本的运算。当两个表达式相邻放置时,就意味着连接。例如,正则表达式“ab”,它表示一个字符‘a’紧接着字符‘b’的序列。在单词描述的情境中,如果我们有一个由两部分组成的标识符模式,比如“prefix_suffix”,我们可以将其看作是“prefix”部分和“suffix”部分的连接,用更详细的正则表达式表示就是“prefix” + “_” + “suffix” 。
- 选择(|):竖线运算符表示选择。例如,正则表达式“a|b”描述了一种模式,即要么出现字符‘a’,要么出现字符‘b’。在描述编程语言中的关键字时,如果有两个相似的关键字,比如“print”和“println”,我们就可以使用类似“print(|ln)”的正则表达式来匹配其中任意一个。
- 克林闭包(*):克林闭包运算符表示前面的元素可以出现零次或多次。如前文提到的,用于描述标识符的正则表达式“[a-zA-Z][a-zA-Z0 - 9]”,就很好地展示了这个运算符。第一部分“[a-zA-Z]”确保标识符以字母开头,第二部分“[a-zA-Z0 - 9]”允许后面跟随任意数量(包括零个)的字母或数字。所以,像“a”“abc123”“x9y”这样的标识符都符合这个模式。
- 正闭包(+):与克林闭包类似,但正闭包运算符要求前面的元素至少出现一次。例如,正则表达式“[0 - 9]+”描述了一个或多个数字的序列。这可以用来表示程序中的正整数,比如“1”“123”“9999” 。
- 括号分组:括号用于将正则表达式的部分内容分组。当我们想对特定的子表达式应用运算符时,这非常有用。例如,在正则表达式“(ab)+”中,括号将“ab”分组,正闭包运算符表示“ab”序列必须出现一次或多次。所以,像“ab”“abab”“ababab”这样的字符串都能匹配这个模式。
2. 在描述不同单词类型中的应用
- 标识符:如前所述,正则表达式“[a-zA-Z][a-zA-Z0 - 9]”全面且准确地描述了标识符。在不同的编程语言中,虽然标识符规则可能存在一些细微差异,但这个基本模式始终是核心部分。例如,在Python中,除了基本的字母数字字符外,标识符还允许使用下划线。所以,一个更符合Python标识符规则的正则表达式可以是“[a-zA-Z_][a-zA-Z0 - 9_]” 。
- 关键字:每种编程语言都有自己的关键字集合。对于像PL/0这样的简单语言,我们可以使用正则表达式对其进行分组和描述。例如,如果考虑关键字“begin”“end”“if”“then”,我们可以创建一个正则表达式“begin|end|if|then”,来匹配源代码中的这些关键字。
- 常量
- 整数常量:对于整数常量,可以使用正则表达式“[-+]?[0 - 9]+” 。“[-+]?”部分是可选的,表示可能存在正号或负号,“[0 - 9]+”确保在符号(如果有)后面至少有一个数字。所以,像“10”“-25”“333”这样的数字都能匹配这个模式。
- 字符串常量:字符串常量通常用特定的定界符括起来。在许多语言中,使用双引号或单引号。例如,要描述一种使用双引号的语言中的字符串常量,可以使用正则表达式“"([^\\n]|(\.))?"” 。这里,外层的双引号定义了字符串的开始和结束。内层部分“([^\\n]|(\.))?”匹配任何不是反斜杠或换行符的字符,或者任何前面带有反斜杠的字符(用于处理转义序列)。所以,像“Hello”“This is a string with \n newline”“a"b”(有适当转义)这样的字符串都能匹配这个模式。
3. 与其他形式化描述工具的比较
虽然正则表达式在描述单词级别的模式方面非常有效,但它并不是唯一可用的形式化描述工具。上下文无关文法(CFGs)是编译器设计工具包中的另一个强大工具。CFGs更适合描述编程语言的整体语法结构,这不仅包括单词级别的构造,还包括单词如何组合形成语句、表达式和程序。例如,一个简单算术表达式的CFGs可能有这样的规则:“表达式 -> 项 + 表达式 | 项”,其中“项”可以进一步根据数字和标识符来定义。相比之下,正则表达式专注于单个单词的构建块。然而,在词法分析的背景下,正则表达式对于定义单个词法单元的结构更具针对性和高效性。在许多情况下,它们也更容易实现,因为可以直接将其转换为有限状态自动机,而有限状态自动机是高效词法分析器的基础。
四、有穷自动机
有穷自动机在词法分析中扮演着核心角色,它能够高效地识别正规式所描述的语言。
(一)确定的有穷自动机DFA
DFA是一种确定性的计算模型,它由状态集合、输入符号集合、转移函数、初始状态和终态集合组成。在DFA中,对于每一个状态和输入符号,都有唯一确定的下一个状态。例如,我们构建一个识别数字的DFA,初始状态为S0,当输入数字字符时,从S0转移到S1,在S1状态下继续输入数字字符会保持在S1状态,直到输入非数字字符,若此时处于终态S1,则表示识别出了一个数字。这种确定性使得DFA在词法分析中能够快速准确地识别单词。
(二)不确定的有穷自动机NFA
与DFA不同,NFA在某些情况下对于同一个状态和输入符号可能有多个转移选择,甚至可以有ε转移(即不消耗输入符号的转移)。NFA的灵活性更高,在描述某些复杂的语言模式时更为方便。例如,在识别包含多种可选模式的单词时,NFA可以通过多个并行的路径来表示不同的选择,而不需要像DFA那样将所有情况都合并到单一的转移路径中。
(三)NFA转换为等价的DFA
由于DFA在实现上更加简单高效,我们常常需要将NFA转换为等价的DFA。转换过程主要基于子集构造法。通过将NFA的状态集合的子集作为DFA的状态,构建DFA的转移函数。例如,NFA中有状态S1、S2,当输入某个符号时,从S1可以转移到S3,从S2可以转移到S4,那么在DFA中,由S1和S2组成的子集状态在输入该符号时,会转移到由S3和S4组成的子集状态。通过这样的方式,逐步构建出与NFA等价的DFA。
(四)确定有穷自动机的化简
化简DFA的目的是减少其状态数量,提高运行效率。常用的方法是基于状态的可区分性。如果两个状态对于所有可能的输入序列都能导致相同的结果(到达终态或非终态),那么这两个状态是不可区分的,可以合并为一个状态。例如,DFA中有状态A和B,无论输入何种符号序列,从A和B出发最终到达的状态要么都是终态,要么都是非终态,那么A和B可以合并,从而减少DFA的状态数量。
五、正规式与有穷自动机的等价性
正规式和有穷自动机之间存在着等价关系。一方面,任何一个正规式都可以转换为一个等价的有穷自动机。通过对正规式的结构进行分析,逐步构建有穷自动机的状态和转移关系。例如,对于正规式“a|b”,可以构建一个有穷自动机,初始状态有两条转移路径,一条在输入a时转移到终态,另一条在输入b时转移到终态。另一方面,任何一个有穷自动机也都可以用一个正规式来描述其识别的语言。通过对有穷自动机的状态和转移关系进行分析,推导出对应的正规式。这种等价性为词法分析提供了多种实现思路,可以根据具体情况选择使用正规式还是有穷自动机来描述和识别单词。
六、正规文法与有穷自动机的等价性
正规文法同样与有穷自动机等价。正规文法分为右线性文法和左线性文法。以右线性文法为例,它的产生式形式为A→aB或A→a(A、B为非终结符,a为终结符)。我们可以将右线性文法的产生式转换为有穷自动机的状态转移。例如,产生式A→aB可以对应有穷自动机中从状态A输入a转移到状态B的操作,A→a对应从状态A输入a转移到终态的操作。反之,有穷自动机也可以转换为正规文法,通过分析有穷自动机的状态和转移关系,构建正规文法的产生式。这种等价性使得我们在词法分析中可以从不同的角度来描述和处理单词识别问题。
七、词法分析程序的自动构造工具
为了提高词法分析程序的开发效率,有许多自动构造工具可供使用,其中lex是较为常用的一种。
(一)lex描述文件中使用的正规表达式
lex描述文件通过正规表达式来定义单词模式。这些正规表达式与我们前面提到的正规式类似,但在lex中有其特定的语法和扩展。例如,可以使用“+”表示前面的字符或字符组出现一次或多次,用“*”表示出现零次或多次等。通过这些丰富的运算符,可以准确地描述各种复杂的单词模式。
(二)lex描述文件的格式
lex描述文件通常分为三个部分:声明部分、规则部分和辅助函数部分。在声明部分,可以定义一些常量、变量以及包含的头文件等。规则部分则是通过正规表达式和对应的动作来定义单词的识别规则,当识别到符合某个正规表达式的单词时,就执行相应的动作,比如返回单词类型等。辅助函数部分可以编写一些自定义的函数,用于规则部分动作的实现。
(三)lex的使用
使用lex时,首先要编写好lex描述文件,然后通过lex工具对该文件进行处理,生成词法分析器的C代码。例如,在命令行中输入“lex lex_file.l”,其中“lex_file.l”是编写好的lex描述文件。lex工具会根据文件中的规则生成相应的C代码,经过编译链接后,就可以得到可执行的词法分析程序。
(四)与yacc的接口约定
yacc是常用的语法分析器生成工具,lex常常与yacc配合使用。在与yacc的接口约定中,lex生成的词法分析器要能够将识别出的单词及其类型传递给yacc进行语法分析。一般通过定义特定的函数和全局变量来实现这种数据传递。例如,lex生成的词法分析器在识别出一个单词后,通过调用特定函数将单词类型和值传递给yacc,yacc根据这些信息进行语法规则的匹配和分析。
通过以上对词法分析的各个方面的介绍,相信大家对词法分析有了更全面深入的理解。从词法分析程序的设计,到各种形式化描述工具、有穷自动机,再到自动构造工具,它们共同构成了词法分析这个重要的编译阶段的完整体系。在实际的编译器开发等工作中,灵活运用这些知识和工具,能够高效地实现词法分析功能,为整个编译流程的顺利进行提供坚实保障。
相关文章:
编译原理——词法分析
文章目录 词法分析:从基础到自动构造一、词法分析程序的设计一、词法分析程序的设计二、PL/0编译程序中词法分析程序的设计与实现1. 语法特定考量2. 通过状态转移表运用有限状态自动机3. 示例代码片段(用于说明的伪代码) 三、单词的形式化描述…...
Linux内核,内存分布
x86_64的物理地址范围为64bit,但是因为地址空间太大目前不可能完全用完,当前支持57bit和48bit两种虚拟地址模式。 地址模式单个空间用户地址空间内核地址空间32位2G0x00000000 - 0x7FFFFFFF0x80000000 - 0xFFFFFFFF64位(48bit)128T0x00000000 00000000 …...
AI鸟类识别技术革新生态监测:快瞳科技如何用“智慧之眼”守护自然?
在生态环境保护日益受关注的今天,“鸟类识别”已从专业科研工具演变为推动生态治理数字化的核心技术。无论是湿地保护区的珍稀候鸟监测,还是城市机场的鸟击风险预警,AI技术的精准赋能正在改写人类与自然的互动方式。作为行业领先的智能解决方…...
c++之set
一、set特性及用途? 唯一性:set 中的元素是唯一的,不会存在重复的元素。自动排序:set 中的元素会自动按照默认的升序规则进行排序。底层实现:set 通常基于红黑树实现,具有自平衡功能,因此插入、…...
【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解
目录 一、前言 二、AI视频概述 2.1 什么是AI视频 2.2 AI视频核心特点 2.3 AI视频应用场景 三、通义万相介绍 3.1 通义万相概述 3.1.1 什么是通义万相 3.2 通义万相核心特点 3.3 通义万相技术特点 3.4 通义万相应用场景 四、DeepSeek 通义万相制作AI视频流程 4.1 D…...
【操作系统】自旋锁和互斥锁
自旋锁和互斥锁是用于多线程同步的两种常见锁机制,主要区别在于等待锁的方式和适用场景。以下是它们的对比分析: 1. 等待机制 自旋锁(Spinlock)互斥锁(Mutex)线程通过 忙等待(Busy-Wait&#x…...
人工智能在医疗影像诊断中的应用与实践
引言 随着人工智能技术的飞速发展,其在医疗领域的应用逐渐成为研究和实践的热点。特别是在医疗影像诊断方面,人工智能技术凭借其强大的数据处理能力和模式识别能力,为提高诊断效率和准确性带来了新的希望。本文将探讨人工智能在医疗影像诊断中…...
Java中synchronized 和 Lock
1. synchronized 关键字 工作原理 对象锁:在Java中,每个对象都有一个与之关联的监视器锁(monitor lock)。当一个线程尝试进入由 synchronized 保护的代码块或方法时,它必须首先获取该对象的监视器锁。如果锁已经被其…...
【C语言系列】数据在内存中存储
数据在内存中存储 一、整数在内存中的存储二、大小端字节序和字节序判断2.1什么是大小端?2.2练习2.2.1练习12.2.2练习22.2.3练习32.2.4练习42.2.5练习52.2.6练习6 三、浮点数在内存中的存储3.1练习3.2浮点数的存储3.2.1 浮点数存的过程3.2.2 浮点数取的过程 3.3题目…...
qt 对QObject::tr()函数进行重定向
在 Qt 中,QObject::tr() 函数用于国际化(i18n),它用于标记需要翻译的字符串。通常情况下,tr() 函数会从翻译文件(如 .qm 文件)中查找对应的翻译字符串。如果你希望重定向 tr() 函数的行为&#…...
C#基础学习(三)值类型和引用类型:编程世界的“现金“ vs “银行卡“,以及string这个“渣男“的叛变行为
开场白 各位程序猿/媛们,今天我们来聊一聊编程世界里的"金钱观"。 你以为只有人类会纠结现金和存款的区别?不不不,C#中的值类型和引用类型每天都在上演这场大戏! 而我们的string同学,表面是…...
自动驾驶背后的数学:多模态传感器融合的简单建模
上一篇博客自动驾驶背后的数学:特征提取中的线性变换与非线性激活 以单个传感器为例,讲解了特征提取中的线性变换与非线性激活。 这一篇将以多模态传感器融合为例,讲解稍复杂的线性变换和非线性激活应用场景。 (一)权重矩阵的张量积分解 y = W x + b = [ w 11 ⋯ w 1 n ⋮…...
如何设置sudo权限
打开终端:按 Ctrl Alt T 打开终端。 编辑 sudoers 文件: 使用 visudo 命令编辑 /etc/sudoers 文件(visudo 会检查语法,避免错误): sudo visudo 添加用户权限: 在文件中找到以下行࿱…...
Codeforces Round 1012 (Div. 2) 3.23
文章目录 2025.3.23 Div2B. Pushing Balls(暴力)代码 C. Dining Hall题意思路代码 2025.3.23 Div2 Dashboard - Codeforces Round 1012 (Div. 2) - Codeforces B. Pushing Balls(暴力) 题意很好懂,每一行每一列从左…...
langfuse追踪Trace
介绍 🧠 Langfuse 是什么? Langfuse 是一个专门为 LLM 应用(如 OpenAI / LangChain / 自定义 Agent) 设计的 观测与追踪平台(Observability Platform)。 简单说,它就像是你为 AI 应用插上的 “…...
Java-模块二-2
整数类型 byte:在 Java 中占用8位(1字节),因此它的取值范围是从 -128 到 127。这是最小的整数类型,适合用于节省空间的情况。 short:这种类型的大小是16位(2字节),允许的…...
使用VS2022编译CEF
前提 选择编译的版本 CEF自动编译,在这里可以看到最新的稳定版和Beta版。 从这里得出,最新的稳定版是134.0.6998.118,对应的cef branch是6998。通过这个信息可以在Build requirements查到相关的软件配置信息。 这里主要看Windows下的编译要…...
大模型RLHF训练-PPO算法详解:Proximal Policy Optimization Algorithms
一、TL;DR 提出了一种新的策略梯度方法家族,用于强化学习,这些方法交替进行与环境交互采样数据提出了一个新的目标函数,使得能够进行多个小批量更新的多轮训练这些新方法为近端策略优化(Proximal Policy Optimization…...
【STM32实物】基于STM32的扫地机器人/小车控制系统设计
基于STM32的扫地机器人/小车控制系统设计 演示视频: 基于STM32的扫地机器人小车控制系统设计 简介:扫地机器人系统采用分层结构设计,主要包括底层硬件控制层、中间数据处理层和上层用户交互层。底层硬件控制层负责对各个硬件模块进行控制和数据采集,中间数据处理层负责对采…...
【C++初阶】从零开始模拟实现vector(含迭代器失效详细讲解)
目录 1、基本结构 1.1成员变量 1.2无参构造函数 1.3有参构造函数 preserve()的实现 代码部分: push_back()的实现 代码部分: 代码部分: 1.4拷贝构造函数 代码部分: 1.5支持{}初始化的构造函数 代码部分: …...
AI比人脑更强,因为被植入思维模型【21】冯诺依曼思维模型
定义 冯诺依曼思维模型是一种基于数理逻辑和系统分析的思维方式,它将复杂的问题或系统分解为若干个基本的组成部分,通过建立数学模型和逻辑规则来描述和分析这些部分之间的关系,进而实现对整个系统的理解和优化。该模型强调从整体到局部、再…...
Keil5调试技巧
一、引言 Keil5作为一款广泛应用于嵌入式系统开发的集成开发环境(IDE),在微控制器编程领域占据着重要地位。它不仅提供了强大的代码编辑和编译功能,还具备丰富的调试工具,帮助开发者快速定位和解决代码中的问题。本文…...
Web PKI现行应用、标准
中国现行 Web PKI 标准 中国在 Web PKI(公钥基础设施)领域制定了多项国家标准,以确保网络安全和数字证书管理的规范性。以下是一些现行的重要标准: 1. GB/T 21053-2023《信息安全技术 公钥基础设施 PKI系统安全技术要求》 该标…...
ROS多机通信(四)——Ubuntu 网卡 Mesh 模式配置指南
引言 使用Ad-hoc加路由协议和直接Mesh模式配置网卡实现的网络结构是一样的,主要是看应用选择, Ad-Hoc模式 B.A.T.M.A.N. / OLSR 优点:灵活性高,适合移动性强或需要优化的复杂网络。 缺点:配置复杂,需手动…...
【实用部署教程】olmOCR智能PDF文本提取系统:从安装到可视化界面实现
文章目录 引言系统要求1. 环境准备:安装Miniconda激活环境 2. 配置pip源加速下载3. 配置学术加速(访问国外资源)4. 安装系统依赖5. 安装OLMOCR6. 运行OLMOCR处理PDF文档7. 理解OLMOCR输出结果9. 可视化UI界面9.1 安装界面依赖9.2 创建界面应用…...
STM32单片机uCOS-Ⅲ系统11 中断管理
目录 一、异常与中断的基本概念 1、中断的介绍 2、和中断相关的名词解释 二、中断的运作机制 三、中断延迟的概念 四、中断的应用场景 五、中断管理讲解 六、中断延迟发布 1、中断延迟发布的概念 2、中断队列控制块 3、中断延迟发布任务初始化 OS_IntQTaskInit() 4…...
CTF【WEB】学习笔记1号刊
Kali的小工具箱 curl www.xxx.com:查看服务器响应返回的信息 curl -I www.xxx.com:查看响应的文件头 一、cmd执行命令 ipconfig:ip地址配置等; 二、 Kali操作 1.sudo su; 2.msfconsole 3.search ms17_010 永恒之蓝ÿ…...
cpp-友元
理解 C 中的友元(Friend) 在 C 语言中,封装(Encapsulation) 是面向对象编程的重要特性之一。它允许类将数据隐藏在私有(private)或受保护(protected)成员中,…...
Spring AOP 核心概念与实践指南
第一章:AOP 核心概念与基础应用 1.1 AOP 核心思想 面向切面编程:通过横向抽取机制解决代码重复问题(如日志、事务、安全等)核心优势:不修改源代码增强功能,提高代码复用性和可维护性 1.2 基础环境搭…...
利用ffmpeg库实现音频Opus编解码
一、编译与环境配置 libopus库集成 需在编译FFmpeg时添加--enable-libopus参数,编译前需先安装libopus源码并配置动态库路径。最新FFmpeg 7.1版本默认支持Opus的浮点运算优化和VBR/CVBR模式。 多平台兼容性 Opus支持Windows/Linux/macOS平台࿰…...
深入理解指针(1)(C语言版)
文章目录 前言一、内存和地址1.1 内存1.2 究竟该如何理解编址 二、指针变量和地址2.1 取地址操作符&2.2 指针变量和解引用操作符*2.2.1 指针变量2.2.2 如何拆解指针类型2.2.3 解引用操作符 2.3 指针变量的大小 三、指针变量类型的意义3.1 指针的解引用3.2 指针-整数3.3 voi…...
计算机网络——通信基础和传输介质
物理层任务:实现相邻节点之间比特(0或1)的传输 到了数据链路层之后,它会以帧为单位,把若干个比特交给物理层,物理层需要把这些比特信息转化成信号,在物理传输媒体上进行传输 通信基础基本概念 信…...
【橘子网络】关于网络分层以及协议的全局讲解
一、网络设备 1、硬件网络设备 1.1、主机(host) 主机的定义比较广泛,所有的接收流量或者发送流量的设备都可以被称之为主机。可以是电脑,手机,服务器。在当今云服务大行其道的局面下,各种云设备也可以被称之为主机。 基于这个…...
macOS 使用 enca 识别 文件编码类型(比 file 命令准确)
文章目录 macOS 上安装 enca基本使用起因 - iconv关于 enca安装 Encaenca & enconv 其它用法 macOS 上安装 enca brew install enca基本使用 enca filepath.txt示例 $ enca 动态规划算法.txt [0] Simplified Chinese National Standard; GB2312CRLF line terminat…...
MySQL 字符集
目录 字符集的基本概念 常见MySQL字符集 ascii(单字节字符集) latin1(单字节字符集) utf8(多字节字符集) utf8mb4(多字节字符集) MySQL默认字符集 MySQL字符集的层次级别 服务器级别 数据库级别 表级别 列级别 连接字符集 字符集是计算机科学中的一个重要概念&…...
Linux shell脚本3-if语句、case语句、for语句、while语句、until语句、break语句、continue语句,格式说明及程序验证
目录 1.if 控制语句 1.1 if 语句格式 1.2 程序验证 2.case语句 2.1case语句格式 2.2程序验证 2.2.1 终端先执行程序,在输入一个数 2.2.2 终端执行程序时同时输入一个预设变量 2.2.3 case带有按位或运算和通配符匹配 3.for语句 3.1for语句格式 3.2程序验…...
基于虚拟知识图谱的语义化决策引擎
在数字化转型浪潮中,企业数据资产的价值释放面临两大挑战:海量异构数据的整合困局与业务-技术语义鸿沟。本文解析飞速创软灵燕智能体平台的创新解决方案——通过构建业务语义驱动的虚拟知识图谱系统,实现企业数据的智能认知与决策赋能。 一、…...
Unity Shader 的编程流程和结构
Unity Shader 的编程流程和结构 Unity Shader 的编程主要由以下三个核心部分组成:Properties(属性)、SubShader(子着色器) 和 Fallback(回退)。下面是它们的具体作用和结构: 1. Pr…...
C++ 继承
目录 一、继承的概念与定义 1.1 继承的概念 1.2 继承的定义 1.2.1 语法 1.2.2 继承关系和访问限定符 1.2.3 继承基类成员访问方式的变化 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 五、C11 final 六、继承与友元 七、继承与静态成…...
XSS Game(DOM型) 靶场 通关
目录 靶场网址 Ma Spaghet! 分析 解题 Jefff 分析 解题 方法一 方法二 Ugandan Knuckles 分析 解题 Ricardo Milos 分析 解题 Ah Thats Hawt 分析 解题 方法一 方法二 Ligma 分析 解题 Mafia 分析 解题 方法一:构造函数 方法二…...
XSS基础靶场练习
目录 1. 准备靶场 2. PASS 1. Level 1:无过滤 源码: 2. level2:转HTML实体 htmlspecialchars简介: 源码 PASS 3. level3:转HTML深入 源码: PASS 4. level4:过滤<> 源码: PASS: 5. level5:过滤on 源码…...
leetcode-200.岛屿数量
首先,想要找岛,肯定是要逐个遍历的,否则肯定会漏岛。 其次,我怎么知道两个点是否属于一个岛?只有一个方法,我踏上一个岛的某个点时,我就分别往四周走,且把当前地块毁掉,就…...
Linux | ubuntu安装 SSH 软件及测试工具
01 windows 要怎么和 ubuntu 互传文件呢,我们可以使用 ssh 软件。 终端输入 sudo apt-get install openssh-server ,输入登录 Ubuntu 用户的密码,这里我们输入 y 确认安装。如下图所示。 接着继续改 ssh 配置文件,因为 ssh 默认…...
组件日志——etcd
目录 一、简介 二、安装【Ubuntu】 安装etcd 安装CAPI 三、写一个示例 3.0写一个示例代码 3.1获取一个etcd服务 3.2获取租约(写端操作) 3.3使用租约(写端操作) 3.4销毁租约(写端操作) 3.5获取etcd服务中的服务列表(读端操作) 3.6监听状态变化(读端操作) 一、简介 Et…...
search_fields与filterset_fields的使用
在Django中,search_fields 和 filterset_fields 可以在视图类中使用,尤其是在 Django REST Framework (DRF) 中。它们分别用于实现搜索和过滤功能。以下是它们在视图类中的具体使用方法。 1. search_fields 在视图类中的使用 search_fields 是 DRF 中 S…...
SQLite Delete 语句详解
SQLite Delete 语句详解 SQLite 是一种轻量级的数据库管理系统,广泛应用于移动设备、嵌入式系统和服务器端应用。在数据库管理中,删除数据是一项基本操作。SQLite 提供了强大的删除功能,本文将详细介绍 SQLite 的 Delete 语句及其用法。 1.…...
通往自主智能之路:探索自我成长的AI
1. 引言:当前AI范式与自我成长智能的愿景 当前的人工智能领域在很大程度上由大型语言模型(LLM)的卓越能力所定义。这些模型,例如OpenAI的GPT系列和谷歌的BERT,已经展示了前所未有的理解和生成类人文本的能力。LLM通常…...
[自动化] 【八爪鱼】使用八爪鱼实现CSDN文章自动阅读脚本
在CSDN上,文章的阅读量往往是衡量内容影响力的一个重要指标。为了测试自动化手段能否提高阅读数,我尝试使用网页自动化工具来模拟人工阅读某个ID的文章。 1. 网页自动化的常见方案 谈到网页自动化,Selenium 是一个最常见的选择。它可以通过…...
Kafka消息序列化深度革命:构建高性能、高安全的自定义编码体系
一、突破默认序列化的桎梏 1.1 原生序列化器的致命缺陷 Kafka默认提供的StringSerializer/ByteArraySerializer在复杂场景下暴露三大痛点: 类型安全黑洞:字节流缺乏元数据描述,消费端解析如履薄冰版本兼容困境:数据结构变更导致…...
2025年如何避免使用验证码求解器时被IP封禁
引言 2025年,验证码求解器已成为自动化网络抓取和其他在线流程的关键工具。然而,自动化用户面临的一个常见挑战是IP封禁。当网站检测到自动化活动时,通常会阻止发出请求的IP地址,导致验证码挑战无法解决。本文将探讨使用验证码求…...