ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

编译原理笔记整理

2021-12-16 19:34:46  阅读:1542  来源: 互联网

标签:语句 文法 终结符 语义 笔记 编译 LR 原理 属性


编译程序的逻辑结构

编译程序逻辑结构上至少包含两大阶段

  • 分析(Analysis)阶段

    理解源程序,挖掘源程序的语义

  • 综合(Synthesis)阶段

    生成与源程序语义上等价的目标程序

编译程序的前端、中端和后端

  • 前端(Front End)

    实现主要的分析任务

    通常以第一次生成中间代码为标志

  • 后端(Back End),与目标机相关

    实现主要的综合任务(目标代码生成和优化)

    通常以从最后一级中间代码生成目标代码为标志

  • 中端(Middle End)

    实现各级中间代码上的操作(中间代码生成与优化)

典型编译程序的逻辑过程

image-20210108174211851

词法分析

词法分析程序(Lexical Analyzer)或词法扫描程序(Scanner)的作用

  1. 从左至右扫描构成源程序的字符流

  2. 识别出有词法意义的单词(Lexemes)

  3. 返回单词记录(由单词记号(Token)和单词的属性值组成),或词法错误信息

  4. 除以上主要任务外,常伴有如下任务

    滤掉空格,跳过注释、换行符,追踪换行标志,复制出错源程序,宏展开,……也可能包含访问符号表的操作

image-20210108174044863

语法分析

image-20210109151316200

判断w是否是文法G的语言,如果是则给出语法分析树。image-20210108174151302

语法分析过程主导语义分析以及翻译的过程

语义分析

对语法分析后的程序进行语义分析,不符合语义规则时给出语义错误信息

image-20210108174338842

符号表

收集每个名字的各种属性用于语义分析及后续各阶段

image-20210108174352813

出错处理

  • 检查错误

    报告出错信息(error reporting)

  • 排错

    恢复编译工作(error recovery)

中间代码生成

抽象语法树 AST

image-20210108174450324

三地址码 TAC

image-20210108174510231

目标代码生成

生成目标机代码

image-20210108174545918

小结: 典型编译程序的主要逻辑模块

image-20210108174608310

文法基础

1. 最左(右)推导

最左推导

image-20210108204328596

image-20210108204343373

最右推导

image-20210108204429422

image-20210108204438459

2. 0~3型文法分类及其包含关系

文法与语言的 Chomsky 分类方法

image-20210108204616628

0 型文法

每个产生式左边至少有一个非终结符

image-20210108204709706

1型文法(上下文有关文法)

每个产生式右边长度都 大于等于 左边长度(除S→ε),且S不出现在右部

image-20210108204849939

2型文法(上下文无关文法)

产生式左边只有一个非终结符

image-20210108204945499

3型文法(正规文法)

产生式左边仅是一个非终结符

产生式右边只由1个终结符(或ε)后面跟0到1个非终结符

能够用3型文法定义的语言称为3型语言或正规语言

image-20210108205145980

文法之间的关系

\[3型文法 \subsetneq 2型文法 \subsetneq 1型文法 \subsetneq 0型文法 \]

3. 画出语法分析树

image-20210108210537045

image-20210108210322031

语法分析树的果实

image-20210108210706420

归约、推导与分析树之间关系

image-20210108210743587

4. 文法的二义性

二义文法(ambiguous grammars)举例

image-20210108210837973

二义文法概念

image-20210108210917514

二义性的判定

image-20210108210926056

消除二义性

image-20210108210935945

正规式、正规文法、自动机

1. DFA 和 NFA 的等价性

定理: L 是某个 DFA 的语言, 当且仅当 L 也是某个 NFA 的语言.

ε - 闭包

image-20210108231456671

个人理解:ε_CLOSURE(I)表示从 集合I 中的每一个元素出发经过 ε边能够到达的点(包括集合I)。

move函数

image-20210108231636460

个人理解:状态集合 I 中的元素经过a边可以到达的点的集合

子集构造法

NFA\(\Rightarrow\)DFA

image-20210108231734775

image-20210108231737066

子集构造法之例

image-20210108232803995

2. DFA 的化简:通过合并等价的(或不可区别的)状态

DFA 状态集合上的一个等价关系定义

image-20210108234456046

DFA 状态集合上等价关系的另一种解释

image-20210108234520232

无关状态

​ 无用状态:从开始状态不能到达的状态
​ 死状态:不能到达终止状态的状态

DFA的简化算法

image-20210108234614499

image-20210108234618162

3. 正规表达式

image-20210109111449341

正规表达式算符优先级

image-20210109111608806

举例

image-20210109111624822

4. 正规式和正规文法的等价

正规式转换为正规文法

tips:未在考试重点

image-20210109111737097

个人理解:第二条可以简化成如下

\[对于形如A\rightarrow x^*y 的正规产生式改写为 A\rightarrow xA|y \]

举例

image-20210109111756312

正规文法转换为正规式

image-20210109111748465

5. 正规式与有穷自动机的等价

image-20210109131143592

从正规表达式构造等价的ε - NFA

image-20210109131549708

image-20210109131553457

image-20210109131556063

image-20210109131558030

image-20210109131604959

典型正规表达式对应的状态转换图

image-20210109131619171

从有限自动机M构造等价的正规表达式r

image-20210109131659281

举例

image-20210109131708152

6. 正规文法与构造有穷自动机的等价

有穷自动机M\(\Rightarrow\)正规文法G

image-20210109133345302

正规文法G构造有穷自动机M

image-20210109133422363

LL(1)自顶向下

1. 消除(直接)左递归

tips:间接左递归不在考点

左递归消除规则

image-20210109160250024

举例

image-20210109160554865

2. 提取左公因子

提取左公因子规则

image-20210109160612656

举例

image-20210109160719183

3. Select集合

First 集合

image-20210109160750370

个人理解:经过任意次推导得到的句型中的第一个终结符

计算 First 集合

image-20210109160858942

个人理解:

  1. 终结符或ε的first集合为自己
  2. 产生式右部为空,即\(A \rightarrow \varepsilon\) First(A)并上\(\varepsilon\)
  3. 产生式右部非空,则First(左部)需并上First(右部)
  4. First(\(Y_1Y_2...Y_k\))。找到第一个First集合不包含\(\varepsilon\)的元素\(Y_i\)。将前面所有元素的First集合并起来,减去\(\{\varepsilon\}\)。如果不存在则所有元素的First集合并起来

Follow 集合(后继符号集)

image-20210109161724804

个人理解:Follow(A)求A后面可能字符串的First集合

计算 Follow 集合

image-20210109161737494

个人理解:如果\(\beta\)为\(\varepsilon\),即A后面无内容,则Follow(A)需并上Follow(X)

Select集(预测集合)(Predictive Set)

image-20210109165331367

4.判断是否为LL(1)文法

image-20210109165434733

举例

image-20210109170101816

5. 画出预测分析表

表驱动 LL(1)分析程序

工作原理:借助于预测分析表和一个下推栈

初始时,下推栈只包含#;首先将文法开始符号入栈;之后依如下步骤:

  1. 若栈顶为终结符,则判断当前读入的单词是否与该终结符相匹配,若匹配,再读取下一单词继续分析;不匹配,则进行出错处理

  2. 若栈顶为非终结符,则根据该非终结符和当前输入单词查预测分析表,若相应表项中是产生式(唯一的),则将此非终结符出栈,并把产生式右部符号从右至左入栈;若表项为空,则进行出错处理

  3. 重复(1)和(2),直到栈顶为 # 同时输入也遇到结束符 # 时,分析结束

预测分析表

  • 表驱动分析程序需要的二维表M

  • 表的每一行A 对应一个非终结符

  • 表的每一列a对应某个终结符或输入结束符 #

  • 表中的项 M(A,a) 表示栈顶为A,下一个输入符号为a时,可选的产生式集合

  • 对于LL(1)文法,可以构造出一个 M(A,a) 最 多只包含一个产生式的预测分析表,可称之为LL(1)分析表

  • M(A,a) 不含产生式时,对应一个出错位置

预测分析表的构造算法

image-20210109171704515

举例

image-20210109171733216

6. 对输入块的分析过程

image-20210109171754968

LR(0)

1. 增广文法

增广文法:使开始符号不会出现在产生式的右部

image-20210109223926381

2. 画出活前缀的DFA

活前缀

image-20210109223934956

活前缀与句柄的关系:一个活前缀是某一右句型的前缀,它不超过该右句型的某个句柄

  • 活前缀已含有该句柄的全部符号,表明该句柄对应的产生式 A→α的右部α已出现在栈顶

  • 活前缀只含该句柄的一部分符号,表明该句柄对应的产生式 A→α1α2 的右部子串α1 已出现在栈顶,期待从输入串中看到α2 推导出的符号串

  • 活前缀不含有该句柄的任何符号,此时期待从输入串中看到该句柄对应的产生式 A→α的右部所推导出的符号串

活前缀集合的归纳定义:

image-20210109224430186

LR(0)FSM 的状态

LR(0)FSM 的状态是一个特殊的 LR(0)项目(item)集

一个LR(0)项目是在右端某一位置有圆点的产生式

image-20210109224927618

LR(0)项目解析

image-20210109225030085

计算LR(0)项目集 I 的闭包 CLOSURE(I)的算法

image-20210109225200356

圆点在产生式右部字符串的某个非终结符前,且该非终结符可以进行推导,则圆点也在该终结符推导出的式子的前面

LR(0)FSM 的初态

image-20210109225244418

例子

image-20210109225255624

LR(0)FSM 的状态转移函数

image-20210109225313225

计算 LR(0)FSM 的所有状态的集合

image-20210109225925463

LR(0)FSM 的构造说明

同一状态的项目集中,若不同项目其后继符号相同时, 后继状态也相同

不同状态的项目集中,若出现相同的项目时,则后继状态也相同. (如后图状态I2和I4同有项目A→.cA故经c均到达状态I2 ,状态I2和I4也同有项目A→.d故经d均到达状态I10 )

LR(0)FSM 的构造举例

image-20210109230145707

LR(0)FSM 的语言

image-20210109233532984

3. 判断是否为LR(0)

LR(0)文法判断

image-20210109230719441

4. action表,goto表

LR分析表

ACTION表

告诉分析引擎:在栈顶状态为k, 当前输入符号是 a 时做什么

ACTION [k,a]=si Shift:状态 i 移进状态栈顶,a移进符号栈顶
ACTION [k,a]=rj Reduce:按第 j 条产生式A→β归约,两栈顶各弹出|β|个元素
ACTION [k,a]=acc Accept :分析完成
ACTION [k,a]=err Error :发现错误 (常标为空白)

GOTO表

GOTO[i,A]=j 告诉分析引擎:在依产生式 A→β 归约依Action完成动作后(两栈顶各弹出|β|个元素),栈顶状态为i 时,要将新状态 j 移进状态栈顶(同时: A 移入符号栈顶)

即:在栈顶状态为k, 当前输入符号是 A时做什么。GOTO表就一个shift操作

LR(0)分析表的构造

image-20210109233547974

LR(0)分析表的构造举例

image-20210110111157195

5. 对输入串的分析过程

LR分析

带符号栈的 LR 分析算法

image-20210109223909375

SLR(1)

LR(0)分析的局限性

image-20210110111243266

发现两个状态(项目集)存在移进-归约冲突

image-20210110111338142

向前查看一个符号可解决冲突

image-20210110111348580

SLR(1)分析思想

  • 向前查看一个符号来改进对LR(0)状态(项目集)中移进-归约和归约-归约冲突的解决
  • 根据下一个输入符号是否属于要归约的非终结符的Follow 集来决定是否进行归约
  • 如果LR(0)状态(项目集)中的所有归约项中要归约的非终结符的 Follow 集互不相交,则可以解决归约-归约冲突
  • 如果LR(0)状态(项目集)中的所有归约项中要归约的非终结符的 Follow 集与所有移进项目要移进的符号集互不相交,则可以解决移进-归约冲突
  • SLR(0)分析表的构造也基于LR(0)FSM
  • 只需对 LR(0)分析表进行简单修改使得归约表项只适用于相应非终结符Follow 集中的输入符号

SLR(1)分析表的构造

image-20210110113757164

image-2021011011133814
image-20210110113606929

SLR(1)文法

image-20210110113632717

比较 LR(0)表和 SLR(1)表

在 LR(0)表的 ACTION 表中,归约表项总是整行出现的,即一个归约对于所有输入符号都适用; 不会既有移进又有归约
而在 SLR(1)表的ACTION 表中。归约表项只适用于相应非终结符Follow 集中的输入符号; 可以既有移进又有归约

LR(1)

LR(1)项目

image-20210115145347193

image-20210115145415498

LR(1)FSM

image-20210115145445428

LR(1)FSM的构造

image-20210115145457839

LR(1)FSM的初态

image-20210115145514768

LR(1)FSM的状态转移函数

image-20210115145533237

计算 LR(1)项目集规范族

image-20210115145542366

LR(1)FSM的构造举例

image-20210115145554611

LR(1)分析表的构造

image-20210115145616167

LR(1)分析表的构造举例

image-20210115145624834

LR(1)文法

image-20210115145633767

语义分析、中间代码

0. 语法制导的语义计算基础(不在考点,前导概念)

概念

  • 属性文法(Attribute Grammar)在上下文无关文法的基础上进行如下扩展

    • 为每个文法符号关联多个属性(Attribute)
    • 为文法的每个产生式关联一个语义规则集合或称为语义动作。
  • 属性

    • 属性(Attribute)可用来刻画一个文法符号的任何我们所关心的特性,如:符号的值,符号的名字串,符号的类型,符号的偏移地址,符号被赋予的寄存器,代码片断,等等…
  • 记号

    • 文法符号 X 关联属性 a 的属性值可通过 X.a 访问
  • 语义规则(Semantic Rule)

    • 在属性文法中,每个产生式 \(A \rightarrow \alpha\) 都关联一个语义规则的集合,用于描述如何计算当前产生式中文法符号的属性值或附加的语义动作
  • 属性文法中允许如下语义规则

    • 复写(copy)规则,形如X.a := Y.b
    • 基于语义函数(semantic function)的规则,形如
      b:=f(c1, c2, …, ck) 或 f(c1, c2, …, ck)
      其中,b,c1, c2, …, ck是该产生式中文法符号的属性
  • 综合属性(synthesized attribute)

    • 用于“自下而上”传递信息

      • 对关联于产生式 \(A \rightarrow \alpha\) 的语义规则 b:=f(c1, c2, …, ck) ,如果 b 是 A 的某个属性, 则称 b 是 A 的一个综合属性
    • 综合属性的例子

      image-20210110162806383

  • 继承属性(inherited attribute)

    • 用于“自上而下”

    • 传递信息对关联于产生式$$A \rightarrow \alpha$$ 的语义规则 b:=f(c1, c2, …, ck) ,如果 b 是产生式右部某个文法符号 X 的某个属性,则称 b 是文法符号 X 的一个继承属性

    • 继承属性的例子

      继承属性代表自上而下传递的信息

      image-20210110163036375

基于属性文法的语义计算

S-属性文法

  • 只包含综合属性
  • 可以自下而上计算分析树中节点的属性

L-属性文法

image-20210110170230987

L-属性文法的语义计算

  • 采用自上而下的方式可以较方便地进行

  • 可以采用下列基于深度优先后序遍历的算法

    image-20210110170413282

  • 该算法与自上而下预测分析过程对应. 因此,基于 LL(1) 文法的 L-属性文法可以采用这种方法进行语义计算.随后将结合翻译模式的进一步讨论分析程序的构造)

采用基于深度优先后序遍历算法进行 L-属性文法的语义计算举例

image-20210110170550355

翻译模式(Translation Scheme)概念

  • 适合语法制导语义计算的另一种描述形式
  • 可以体现一种合理调用语义动作的翻译算法
  • 形式上类似于属性文法,但允许由{ }括起来的语义规则集合出现在产生式右端的任何位置. 这样做的好处是可以显式地表达动作和属性计算的次序,而在前述的属性文法中不体现这种次序

受限的翻译模式

  • 在设计翻译模式时,必须作某些限制,以确保每个属性值在被访问到的时候已经存在
  • 本讲仅讨论两类受限的翻译模式
    • S-翻译模式,为仅需要综合属性的情形,创建一个语义规则集合,放在相应产生式右端的末尾,把属性的计算规则加入其中即可。该模式类似与S-属性文法,不重复讨论
    • L-翻译模式,对于既包含继承属性又包含综合属性的情形,但需要满足:
      • (1)产生式右端某个符号继承属性的计算必须位于该符号之前,其语义动作不访问位于它右边符号的属性,只依赖于该符号左边符号的属性(对于产生式左部的符号,只能是继承属性)
      • (2)产生式左部非终结符的综合属性的计算只能在所用到的属性都已计算出来之后进行,通常将相应的语义动作置于产生式的尾部

翻译模式举例

定点二进制小数转换为十进制小数

image-20210110165727098

1. 声明语句的属性文法

类型表达式(type expressions)

由基本类型,类型名字,类型变量,及类型构造子 (type constructor)归纳定义的表达式

分四类定义

  • 基本数据类型表达式

    • 纯量类型表达式:bool, int, real

    • 有界数组类型表达式:array(I,T)

      T∈{ bool, int, real };I 代表一个整数区间,如 1..10

    • 指针数据类型表达式:pointer(T)

      T∈{ bool, int, real }

  • 积类型表达式

    • <T1, T2, …, Tn>

      T1, T2, …, Tn 为上述数据类型表达式;若n=0,则表示为 < >

  • 过程类型表达式

    • fun(T)T 是上述积类型表达式
  • 专用类型表达式

    • type_error 专用于有类型错误的程序单元
    • ok 专用于没有类型错误的程序单元

语义函数

make_product_3 (V1.type, T.type, L.num) 生成积类型表达式< t1,…,tm,T.type,…,T.type>T.type共L.num个,V1.type=<t1,…,tm> 。
num.lexval 为词法分析返回的单词属性值
id.entry 指向当前标识符对应于符号表中的表项
addtype(id.entry,L.in) 表示将属性值 L.in 填入当前标识符在符号表表项中的type 域( 记录标识符的类型)
id.name 为当前标识符的名字;
lookup_type(id.name) 从符号表中查找名字为 id.name 的标识符所对应的表项中 type 域的内容,若未查到该表项或表项中的 type 域无定义,则返回 nil。
type_error 专用于有类型错误的程序单元
ok 专用于没有类型错误的程序单元
match( fun (type1), type2) 返回 true,当且仅当 type1, type2 是完全相同的积类型表达式
id.place id 对应的存储位置
E.place 用来存放 E 的值的存储位置
E.code E 求值的 TAC 语句序列(可不止一条四元式)
S.code 对应于 S 的 TAC 语句序列
newtemp 在符号表中新建一个名字,返回该名字存储位置
newlabel 返回一个新的语句标号
gen 生成一条 TAC 语句
|| TAC 语句序列之间的链接运算

类型检查程序的设计

语法制导的方法

  • 将类型表达式作为属性值赋给程序各个部分
  • 设计恰当的翻译模式
  • 可实现相应语言的一个类型系统

语法制导的类型检查程序 —— 举例

处理声明的翻译模式

image-20210110172534352

image-20210110174900720

处理表达式的翻译模式(不在考点)

image-20210110173013237

image-20210110173023975

处理语句、过程声明及程序的翻译模式(不在考点)

image-20210110173103986

image-20210110173124815

2. 写出四元式序列(布尔表达式,短路求值)

布尔表达式的语法制导翻译

image-20210110210127385

直接对布尔表达式求值

image-20210110210136859

翻译流程控制布尔表达式至短路代码(L-翻译模式)

image-20210110210149809

语法分析树

image-20210110210305133

通过控制流体现布尔表达式的语义

image-20210110210320496

运行时存储组织

1. 栈区、活动记录、静态链和动态链

栈式存储分配

  • 用于有效实现可动态嵌套的程序结构
    • 如实现过程/函数,递归,块层次结构
    • 比较:静态分配不宜实现递归过程/函数
  • 运行的时候才能确定数据对象的存储分配结果
  • 过程/函数的实现中,运行栈中的数据单元是活动记录(activation record,后面专门讨论)
    • 运行时每当进入一个过程/函数,就在栈顶为该过程/函数分配存放活动记录的数据空间;工作完毕返回时,栈顶的活动记录数据空间随即释放
    • 在过程/函数的某一次执行中,其活动记录中会存放生存期在该过程/函数本次执行中的数据对象,以及必要的控制信息单元。
    • 在编译期间, 过程/ 函数以及嵌套程序块的活动记录大小(最大值) 应该是可以确定的,如果不满足则应该使用堆式存储管理

活动记录

函数/过程调用或返回时,在运行栈上创建或从运行栈上消去的栈帧(frame)

包含局部变量,函数实参,临时值(用于表达式计算的中间单元)等数据信息以及必要的控制信息

image-20210114213106246

过程活动记录的栈式分配举例

image-20210114213114752

典型的过程活动记录结构

image-20210114213206427

活动过程记录举例

image-20210114213225004

静态链

Display 表的方法要用到多个存储单元或多个寄存器。

一种可选的方法是采用静态链,也称访问链、存取链

所有活动记录都增加一个静态链(如在offset 为 0 处)的域,指向定义该过程的直接外过程(或主程序)运行时最新的活动记录

过程返回时, 当前活动记录要被撤销,为回( unwind)到调用过程的活动记录(恢复FP),需要在被调用过程的活动记录中有这样一个域,即动态链,指向该调用过程的活动记录(的基址),也称控制链

个人理解:静态链指向定义该过程的外过程,动态链指向调用该过程的外过程

静态链动态链举例

image-20210115152600104

代码生成

1. 支配节点集、回边、自然循环

基本块(basic block)

概念

  • 程序中一个顺序执行的语句序列
  • 只有一个入口语句和一个出口语句
  • 除入口语句外其他语句均不可以带标号
  • 除出口语句外其他语句均不可能是转移或停语句

入口语句

  • 程序的第一个语句
  • 条件转移语句或无条件转移语句的转移目标语句
  • 紧跟在条件转移语句后面的语句

划分基本块的算法

  • 针对三地址码(TAC)

  • 步骤

    • 出 TAC 程序之中各个基本块的入口语句
    • 对每一入口语句,构造其所属的基本块。它是由该语句到下一入口语句(不包括下一入口语句),或到一转移语句(包括该转移语句),或到一停语句(包括该停语句)之间的语句序列组成的
    • 凡未被纳入某一基本块的语句,都是程序中控制流程无法到达的语句,因而也是不会被执行到的语句,可以把它们删除
  • 举例

    image-20210114222417291

流图(flow graph)

概念

  • 可以为构成程序的基本块增加控制流信息,方法是构造一个有向图,称之为流图或控制流图(CFG,Control-Flow Graph)

流图以基本块集为结点集;第一个结点为含有程序第一条语句的基本块;从基本块 i 到基本块 j 之间存在有向边当且仅当

  • 基本块 j 在程序的位置紧跟在 i 后,且 i 的出口语句不是转移 (可为条件转移)语句、停语句或者返回语句;
  • 或者i 的出口是 goto(S) 或 if …goto(S), 而 (S) 是 j 的入口语句

举例

image-20210114222714829

循环(loop)

支配结点集(dominators)

如果从流图的首结点出发,到达 n 的任意通路都要经过 m,则称 m 支配 n, 或 m 是 n 的支配结点,记为 m DOM n(∀a. a DOM a)

结点n 的所有支配结点的集合, 称为结点 n 的支配结点集,记为D(n)

注意:支配结点也称必经节点,支配节点集也称必经节点集

支配结点集举例

image-20210114222832927

自然循环(natural loop)

假设 n→d 是流图中的一条有向边,如果 d DOM n 则称 n→d 是流图中的一条回边(back edge)

有向边 n→d 是回边,它对应的自然循环是由结点 d ,结点 n 以及有通路到达 n 而该通路不经过 d 的所有结点组成,并且 d 是该循环的唯一入口结点

同时,因 d 是 n 的支配结点,所以 d 必可达该循环中任意结点

注:流图中的任何结点都是从首结点可达的

自然循环举例

image-20210114222835236

标签:语句,文法,终结符,语义,笔记,编译,LR,原理,属性
来源: https://www.cnblogs.com/EIPsilly/p/15699694.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有