经典c编程架构
- 格式:doc
- 大小:61.00 KB
- 文档页数:15
C语言中的结构化编程和函数模块化在软件开发过程中,结构化编程和函数模块化是两个非常重要的概念。
它们能够帮助程序员更好地组织代码、提高代码的可读性和模块化程度,从而提高软件的开发效率和维护性。
本文将介绍C语言中的结构化编程和函数模块化,并探讨如何应用这些概念来写出高效、可维护的C语言程序。
一、结构化编程结构化编程是一种编程范式,它的核心思想是将程序分解为多个小而独立的模块,每个模块有一个特定的功能,并通过顺序、选择和循环等结构将这些模块连接起来。
结构化编程强调代码的结构化和逻辑的清晰性,以及消除程序中的混乱和难以理解的部分。
在C语言中,结构化编程的实现主要依赖于函数和控制结构。
1. 函数函数是C语言中实现结构化编程的基本组织单位。
通过将代码划分为多个函数,每个函数具有特定的功能,可以让程序更易于理解、修改和测试。
在编写函数时,需要遵循一些规范和最佳实践:- 函数应该具有良好的命名,能够准确地描述函数的功能。
- 每个函数应该只负责一个具体的任务,遵循“单一职责原则”。
- 函数的参数应该被合理地设计,避免参数过多或过少。
- 函数应该尽可能地短小,每个函数的代码行数应该控制在一个可读性良好的范围内。
- 函数应该遵循“高内聚、低耦合”的原则,减少代码之间的依赖关系。
2. 控制结构控制结构用于控制程序的执行流程,常见的控制结构包括顺序结构、选择结构和循环结构。
在编写结构化程序时,需要合理地运用这些控制结构来实现代码逻辑的清晰化。
- 顺序结构:代码按照从上到下的顺序依次执行。
- 选择结构:根据条件判断选择执行不同的代码块,例如if语句和switch语句。
- 循环结构:根据条件重复执行代码块,例如while循环和for循环。
二、函数模块化函数模块化是将程序分解为多个模块或功能块,并通过调用这些模块来实现程序的功能。
函数模块化能够提高代码的可重用性和可维护性,减少了代码的重复编写和修改。
在C语言中,实现函数模块化通常包括以下几个步骤:1. 功能划分将程序的功能划分为多个小而独立的模块。
c语言3大基本结构C语言是一种广泛应用的编程语言,其简洁高效的特点使其成为了许多程序员的首选语言。
在学习C语言时,了解它的基本结构是非常重要的。
C语言中有三个基本结构,分别是顺序结构、选择结构和循环结构。
下面将详细介绍这三种基本结构。
一、顺序结构顺序结构是指程序按照代码书写顺序依次执行的过程。
在C语言中,每一行代码都会按照书写顺序被执行。
例如:```#include <stdio.h>int main(){printf("Hello, World!\n");printf("This is my first C program.\n");return 0;}```以上代码就是一个典型的顺序结构程序。
程序从第一行开始执行,按照代码书写顺序依次执行每一行代码,直到程序结束。
二、选择结构选择结构是指根据条件判断来决定程序执行哪些代码段。
在C语言中,选择结构主要有if语句和switch语句两种形式。
1. if语句if语句可以根据条件判断来决定是否执行某段代码。
其基本形式如下:```if (condition){// 如果condition为真,则执行这里的代码}else{// 如果condition为假,则执行这里的代码}```例如:```#include <stdio.h>int main(){int a = 10;if (a > 0){printf("a是正数\n");}else{printf("a是负数或零\n");}return 0;}```以上代码中,if语句根据变量a的值判断是否为正数,如果是则输出"a是正数",否则输出"a是负数或零"。
2. switch语句switch语句也可以根据条件判断来决定执行哪些代码段。
其基本形式如下:```switch (expression){case value1:// 如果expression等于value1,则执行这里的代码break;case value2:// 如果expression等于value2,则执行这里的代码break;default:// 如果expression不等于任何一个case中的值,则执行这里的代码break;}```例如:```#include <stdio.h>int main(){int score = 85;switch (score / 10) {case 10:case 9:printf("优秀\n"); break;case 8:printf("良好\n"); break;case 7:printf("中等\n");break;case 6:printf("及格\n");break;default:printf("不及格\n");break;}return 0;}```以上代码中,switch语句根据变量score的值判断成绩等级,根据不同的分数段输出不同的信息。
c语言三层架构简介
c语言三层架构简介
三层架构答案:通常意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。
区分层次的目的即为了“高内聚,低耦合”的思想。
表现层(UI):通俗讲就是展现给用户的界面,即用户在使用一个系统的.时候的所见所得。
业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。
数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增添、删除、修改、更新、查找等每层之间是一种垂直的关系。
三层结构是N层结构的一种,一般来说,层次之间是向下依赖的,下层代码未确定其接口(契约)前,上层代码是无法开发的,下层代码接口(契约)的变化将使上层的代码一起变化。
优点:分工明确,条理清晰,易于调试,而且具有可扩展性。
缺点:增加成本。
c语言中描述线程与进程的区别?
1.线程(Thread)与进程(Process)二者都定义了某种边界,不同的是进程定义的是应用程序与应用程序之间的边界,不同的进程之间不能共享代码和数据空间,而线程定义的是代码执行堆栈和执行上下文的边界。
2.一个进程可以包括若干个线程,同时创建多个线程来完成某项任务,便是多线程。
而同一进程中的不同线程共享代码和数据空间。
用一个比喻来说,如果一个家庭代表一个进程,在家庭内部,各个成员就是线程,家庭中的每个成员都有义务对家庭的财富进行积累,同时也有权利对家庭财富进行消费,当面对一个任务的时候,家庭也可以派出几个成员来协同完成,而家庭之外的人则没有办法直接消费不属于自己家庭的财产。
【c语言三层架构简介】。
C语言算法及三种基本程序结构C语言算法及三种基本程序结构大家知道C语言都有哪些算法吗?这些算法的程序结构是怎么样的呢?下面店铺为大家整理了C语言算法及三种基本程序结构,希望能帮到大家!算法做任何事情都有一定的步骤。
为解决一个问题而采取的方法和步骤,就称为算法。
算法是一个基本的概念,但也是一门深奥的学问,小到如何输出九九乘法表,如何对一组数据进行排序,大到如何控制飞行器的姿态,如何让无人机壁障。
这里主要是向大家阐述一下算法的概念,对于初学者,涉及到的算法都很简单,一般不会成为学习的障碍,我们会在后面的实例中逐渐向大家渗透具体的算法。
请大家思考一个问题:如何求1×2×3×4×5的值。
最原始方法:步骤1:先求1×2,得到结果2。
步骤2:将步骤1得到的乘积2乘以3,得到结果6。
步骤3:将6再乘以4,得24。
步骤4:将24再乘以5,得120。
这样的算法虽然正确,但太繁。
改进的算法:S1:使t=1S2:使i=2S3:使t×i,乘积仍然放在在变量t中,可表示为t×i -> tS4:使i的值+1,即 i+1 -> iS5:如果i≤5,返回重新执行步骤S3以及其后的S4和S5;否则,算法结束。
如果计算100!只需将“S5:若i≤5”改成“i≤100”即可。
如果改成求1×3×5×7×9×11,算法也只需做很少的改动:S1:1 -> tS2:3 -> iS3:t×i -> tS4:i+2 -> iS5:若i≤11,返回S3;否则,结束。
该算法不仅正确,而且是计算机较好的算法,因为计算机是高速运算的自动机器,实现循环轻而易举。
三种基本程序结构几乎所有编程语言,包括C语言,都会有三种基本的程序结构:顺序结构、选择结构和循环结构。
顺序结构顺序结构就是一条一条地从上到下执行语句,所有的语句都会被执行到,执行过的语句不会再次执行。
c语言的整体框架结构C语言是一种通用的高级程序设计语言,其框架结构主要包括输入输出、基本数据类型、控制结构、函数和库五个方面。
下面将详细介绍C语言的整体框架结构。
1. 输入输出(Input/Output):C语言提供了一组标准库函数来实现输入和输出操作,使得程序可以与用户进行交互。
常用的输入函数有scanf()和fgets(),用于从键盘读取用户输入的数据;常用的输出函数有printf()和puts(),用于将结果输出到屏幕。
通过这些输入输出函数,程序可以接收用户的输入,并将结果展示给用户,实现与用户的交互。
2. 基本数据类型(Basic Data Types):C语言提供了一些基本的数据类型,包括整型、浮点型、字符型等。
整型包括int、short、long和long long等,用于表示整数;浮点型包括float和double,用于表示实数;字符型用于表示单个字符。
这些数据类型可以根据需要进行组合和扩展,以满足程序对不同类型数据的需求。
3. 控制结构(Control Structures):C语言提供了一些控制结构来进行程序的流程控制,包括顺序结构、选择结构和循环结构。
顺序结构指的是程序从上到下顺序执行;选择结构包括if语句和switch语句,用于根据条件选择不同的执行路径;循环结构包括for循环、while循环和do-while循环,用于重复执行一段代码。
通过这些控制结构,可以实现对程序流程的灵活控制,使程序可以根据不同的条件做出不同的处理。
4. 函数(Functions):C语言支持函数的定义和调用,通过函数可以将一段代码封装成一个独立的模块,以达到代码复用和模块化的目的。
函数可以接受参数,并返回一个值。
参数用于传递数据给函数,函数内部对参数进行处理,可以改变参数的值或返回结果;返回值用于将计算结果返回给函数的调用者。
函数可以使程序结构更加清晰,简化程序设计过程,并提高代码的可读性和可维护性。
C语言的三种结构C语言中的三种结构分别是:顺序结构、选择结构和循环结构。
一、顺序结构顺序结构是程序中最常见的一种结构,它是按照代码编写的顺序依次执行每一条语句,没有任何跳转、循环或者分支。
顺序结构的特点是执行效率高,代码量简单,并且易于理解和维护。
例如,以下是一个简单的顺序结构程序:```c#include <stdio.h>上述程序的执行顺序是从第3条语句开始依次执行,先计算a和b的和,然后将结果赋值给变量c,并最后输出结果。
这符合程序的逻辑执行顺序。
二、选择结构选择结构是根据条件的真假决定程序的执行路径,可以使程序有多种不同的执行方式,通常以if语句或switch语句来实现。
1. if语句if语句是一种条件控制结构,它根据指定的条件表达式的结果,选择执行或跳过特定的代码块。
if语句的语法格式如下:```cif ( expression ){statement(s); //条件为真时执行}```例如,以下是一个使用if语句的程序:return 0;}```上述程序会输出"a 小于 20"和"a 的值是10",其中if语句判断a是否小于20,若为真则执行printf函数输出相应的字符串,若为假则跳过if语句直接执行后面的printf函数。
2. switch语句switch语句是根据变量或表达式的值来选择执行不同的代码块,其语法格式如下:```cswitch(expression){case constant-expression :statement(s);break; //可选的 case 常量表达式case constant-expression :statement(s);break;default : //可选的 default 语句statement(s);}```switch(grade){case 'A' :printf("优秀\n" );break;case 'B' :case 'C' :printf("良好\n" );break;case 'D' :printf("及格\n" );break;case 'F' :printf("不及格\n" );break;default :printf("无效的成绩\n" );}上述程序中,变量grade的值为'B',switch语句根据其值来选择执行不同的代码块,由于grade的值是'B',所以执行case 'B'和case 'C'中的语句并输出"良好",最后输出变量grade的值。
C语言的四种程序结构C语言具有以下四种程序结构:1.顺序结构:顺序结构是指按照程序的顺序依次执行语句的结构。
C语言程序中,语句是按照它们在源代码中出现的顺序被执行的。
例如,以下是一个简单的顺序结构的示例:```c#include <stdio.h>int maiint num1 = 5;int num2 = 10;int sum = num1 + num2;printf("The sum of %d and %d is %d", num1, num2, sum);return 0;```上述例子中,程序按照从上到下的顺序依次执行,首先定义了两个整数变量`num1`和`num2`,然后计算它们的和,并将结果存储在变量`sum`中,最后通过`printf`函数打印出结果。
2.分支结构:分支结构是通过条件来决定程序执行路径的结构。
根据条件表达式的真假,程序将决定执行哪个分支。
C语言中的分支结构通常使用if-else和switch语句来实现。
以下是一个使用if-else语句的分支结构的示例:```c#include <stdio.h>int maiint num = 10;if (num > 0)printf("Number is positive");} elseprintf("Number is negative");}return 0;```上述例子中,程序根据变量`num`的值决定执行哪个分支。
如果`num`大于0,将打印"Number is positive";否则,将打印"Number is negative"。
3.循环结构:循环结构是一个重复执行其中一段代码的结构。
在C语言中,循环结构可以使用for、while和do-while语句来实现。
以下是一个使用for循环的示例:```c#include <stdio.h>int maiint i;for (i = 0; i < 5; i++)printf("%d\n", i);}return 0;```上述例子中,循环执行了5次,每次循环打印变量`i`的值。
c程序的基本结构C程序的基本结构通常包括以下几个部分:1. 头文件引用:使用#include命令引入需要使用的库函数的头文件,例如#include<stdio.h>表示引入标准输入输出库函数的头文件。
2. 定义全局变量:在main函数之外定义需要在整个程序中使用的全局变量。
3. 函数声明:在main函数之前声明自定义函数的原型,以便在main函数中调用。
4. main函数:程序的入口函数,其中包含程序的主要逻辑。
5. 自定义函数实现:在main函数之后编写自定义的函数,并在main函数中调用。
6. 返回语句:使用return命令返回程序执行的结果。
下面是一个简单C程序的基本结构示例:```c#include<stdio.h>// 函数声明int add(int num1, int num2);// 全局变量定义int globalVar = 100;int main(){// 主要逻辑int a = 10;int b = 20;int sum = add(a, b);printf("The sum is %d\n", sum);return 0;}// 自定义函数实现int add(int num1, int num2){return num1 + num2;}```这个程序的基本结构包括了头文件引用、全局变量定义、函数声明、main函数、自定义函数实现以及返回语句。
在main函数中调用了自定义的add函数,实现了两个整数相加并输出结果。
最后使用return命令返回0,表示程序正常结束。
c语言知识框架
C语言是一种高级的、通用的计算机编程语言,具有强大的表达能力和广泛的应用范围。
在掌握C语言的过程中,我们需要建立一个坚实的知识框架,以便逐步提高我们的编程水平。
下面是一个C语言知识框架的概述:
1.基础知识
C语言的基础知识包括数据类型、变量、常量、运算符、控制语句等。
这些知识点对于编写任何C程序都是必不可少的。
2.函数库
C语言的标准函数库包含大量的函数,在编写程序的过程中可以调用这些函数来完成某些任务,例如输入输出、字符串处理、数学运算等。
3.文件操作
文件操作是C语言的一个重要部分,它允许我们读取和写入文件。
了解文件操作的知识可以帮助我们在程序中保存和加载数据。
4.指针
指针是C语言的一个强大特性,它允许我们直接访问内存中的数据。
掌握指针的知识可以帮助我们更好地理解C语言本身以及其他编程语言。
5.结构体
结构体是一种用户自定义的数据类型,它允许我们将不同类型的数据组合在一起形成一个新的数据类型。
它在C语言中的应用非常广
泛。
6.动态内存分配
动态内存分配允许我们在程序运行时动态地分配内存。
这是一种非常强大的特性,它可以帮助我们在程序运行时更有效地利用内存。
7.高级主题
C语言还有许多高级主题,例如多线程、网络编程、并发等。
掌握这些主题可以帮助我们编写更加高效和复杂的程序。
以上是C语言知识框架的一个简要概述。
在掌握和理解这些知识点的基础上,我们可以更好地编写高质量的C语言程序。
C语言程序的基本结构一、预处理指令预处理指令以“#”符号开头,用于提供指示器供编译器使用。
预处理指令可以包括文件包含、宏定义和条件编译等。
1. 文件包含:使用预处理指令“#include”可以将其他头文件包含到当前源文件中,以便可以使用其中定义的函数和变量。
```c#include <stdio.h>```2. 宏定义:使用预处理指令“#define”可以定义宏,宏会在编译前被展开为相应的代码。
```c```3. 条件编译:使用预处理指令“#ifdef”、“#ifndef”、“#if”等可以根据条件选择是否编译段代码。
```c#ifdef DEBUGprintf("Debugging mode\n");#endif```二、全局变量全局变量是在函数外部定义的变量,可以在整个程序中被访问和使用。
全局变量必须在使用之前进行声明或定义。
```c#include <stdio.h>int globalVariable;int mai// do somethingreturn 0;```三、函数声明函数声明用于告诉编译器有一个函数存在,它的名称、参数和返回类型等信息。
函数声明一般放在头文件中,可以被多个源文件共享。
```c#include <stdio.h>int add(int a, int b);int maiint result = add(3, 5);printf("Result: %d\n", result);return 0;int add(int a, int b)return a + b;```四、函数定义函数定义包含了函数的具体实现,函数定义一般放在源文件中,用于实现函数的功能。
```c#include <stdio.h>int add(int a, int b)return a + b;int maiint result = add(3, 5);printf("Result: %d\n", result);return 0;```五、函数调用函数调用是通过函数名和参数列表来调用函数,可以将函数的返回值赋给变量或直接输出结果。
1. 顺序执行法:这种方法,这应用程序比较简单,实时性,并行性要求不太高的情况下是不错的方法,程序设计简单,思路比较清晰。
但是当应用程序比较复杂的时候,如果没有一个完整的流程图,恐怕别人很难看懂程序的运行状态,而且随着程序功能的增加,编写应用程序的工程师的大脑也开始混乱。
即不利于升级维护,也不利于代码优化。
本人写个几个比较复杂一点的应用程序,刚开始就是使用此法,最终虽然能够实现功能,但是自己的思维一直处于混乱状态。
导致程序一直不能让自己满意。
这种方法大多数人都会采用,而且我们接受的教育也基本都是使用此法。
对于我们这些基本没有学习过数据结构,程序架构的单片机工程师来说,无疑很难在应用程序的设计上有一个很大的提高,也导致了不同工程师编写的应用程序很难相互利于和学习。
本人建议,如果喜欢使用此法的网友,如果编写比较复杂的应用程序,一定要先理清头脑,设计好完整的流程图再编写程序,否则后果很严重。
当然应该程序本身很简单,此法还是一个非常必须的选择。
下面就写一个顺序执行的程序模型,方面和下面两种方法对比:代码:/******************************************************************** ******************* FunctionName : main()* Description : 主函数* EntryParameter : None* ReturnValue : None********************************************************************* *****************/int main(void){uint8 keyValue;InitSys(); // 初始化while (1){TaskDisplayClock();keyValue = TaskKeySan();switch (keyValue){case x: TaskDispStatus(); break;...default: break;}}}2. 时间片轮询法时间片轮询法,在很多书籍中有提到,而且有很多时候都是与操作系统一起出现,也就是说很多时候是操作系统中使用了这一方法。
不过我们这里要说的这个时间片轮询法并不是挂在操作系统下,而是在前后台程序中使用此法。
也是本贴要详细说明和介绍的方法。
对于时间片轮询法,虽然有不少书籍都有介绍,但大多说得并不系统,只是提提概念而已。
下面本人将详细介绍本人模式,并参考别人的代码建立的一个时间片轮询架构程序的方法,我想将给初学者有一定的借鉴性。
记得在前不久本人发帖《1个定时器多处复用的问题》,由于时间的问题,并没有详细说明怎样实现1个定时器多处复用。
在这里我们先介绍一下定时器的复用功能。
使用1个定时器,可以是任意的定时器,这里不做特殊说明,下面假设有3个任务,那么我们应该做如下工作:1. 初始化定时器,这里假设定时器的定时中断为1ms(当然你可以改成10ms,这个和操作系统一样,中断过于频繁效率就低,中断太长,实时性差)。
2. 定义一个数值:复制内容到剪贴板代码:#define TASK_NUM (3) // 这里定义的任务数为3,表示有三个任务会使用此定时器定时。
uint16 TaskCount[TASK_NUM] ; // 这里为三个任务定义三个变量来存放定时值uint8 TaskMark[TASK_NUM]; // 同样对应三个标志位,为0表示时间没到,为1表示定时时间到。
3. 在定时器中断服务函数中添加:复制内容到剪贴板代码:/******************************************************************** ******************* FunctionName : TimerInterrupt()* Description : 定时中断服务函数* EntryParameter : None* ReturnValue : None********************************************************************* *****************/void TimerInterrupt(void){uint8 i;for (i=0; i<TASKS_NUM; i++){if (TaskCount[i]){TaskCount[i]--;if (TaskCount[i] == 0){TaskMark[i] = 0x01;}}}}代码解释:定时中断服务函数,在中断中逐个判断,如果定时值为0了,表示没有使用此定时器或此定时器已经完成定时,不着处理。
否则定时器减一,知道为零时,相应标志位值1,表示此任务的定时值到了。
4. 在我们的应用程序中,在需要的应用定时的地方添加如下代码,下面就以任务1为例:复制内容到剪贴板代码:TaskCount[0] = 20; // 延时20msTaskMark[0] = 0x00; // 启动此任务的定时器到此我们只需要在任务中判断TaskMark[0] 是否为0x01即可。
其他任务添加相同,至此一个定时器的复用问题就实现了。
用需要的朋友可以试试,效果不错哦。
通过上面对1个定时器的复用我们可以看出,在等待一个定时的到来的同时我们可以循环判断标志位,同时也可以去执行其他函数。
循环判断标志位:那么我们可以想想,如果循环判断标志位,是不是就和上面介绍的顺序执行程序是一样的呢?一个大循环,只是这个延时比普通的for循环精确一些,可以实现精确延时。
执行其他函数:那么如果我们在一个函数延时的时候去执行其他函数,充分利用CPU时间,是不是和操作系统有些类似了呢?但是操作系统的任务管理和切换是非常复杂的。
下面我们就将利用此方法架构一直新的应用程序。
时间片轮询法的架构:1.设计一个结构体:复制内容到剪贴板代码:// 任务结构typedef struct _TASK_COMPONENTS{uint8 Run; // 程序运行标记:0-不运行,1运行uint8 Timer; // 计时器uint8 ItvTime; // 任务运行间隔时间void (*TaskHook)(void); // 要运行的任务函数} TASK_COMPONENTS; // 任务定义这个结构体的设计非常重要,一个用4个参数,注释说的非常详细,这里不在描述。
2. 任务运行标志出来,此函数就相当于中断服务函数,需要在定时器的中断服务函数中调用此函数,这里独立出来,并于移植和理解。
复制内容到剪贴板代码:/******************************************************************** ******************* FunctionName : TaskRemarks()* Description : 任务标志处理* EntryParameter : None* ReturnValue : None**************************************************************************************/void TaskRemarks(void){uint8 i;for (i=0; i<TASKS_MAX; i++) // 逐个任务时间处理{if (TaskComps[i].Timer) // 时间不为0{TaskComps[i].Timer--; // 减去一个节拍if (TaskComps[i].Timer == 0) // 时间减完了{TaskComps[i].Timer = TaskComps[i].ItvTime; // 恢复计时器值,从新下一次TaskComps[i].Run = 1; // 任务可以运行}}}}大家认真对比一下次函数,和上面定时复用的函数是不是一样的呢?3. 任务处理复制内容到剪贴板代码:/******************************************************************** ******************* FunctionName : TaskProcess()* Description : 任务处理* EntryParameter : None* ReturnValue : None********************************************************************* *****************/void TaskProcess(void){uint8 i;for (i=0; i<TASKS_MAX; i++) // 逐个任务时间处理{if (TaskComps[i].Run) // 时间不为0{TaskComps[i].TaskHook(); // 运行任务TaskComps[i].Run = 0; // 标志清0}}}此函数就是判断什么时候该执行那一个任务了,实现任务的管理操作,应用者只需要在main()函数中调用此函数就可以了,并不需要去分别调用和处理任务函数。
到此,一个时间片轮询应用程序的架构就建好了,大家看看是不是非常简单呢?此架构只需要两个函数,一个结构体,为了应用方面下面将再建立一个枚举型变量。
下面我就就说说怎样应用吧,假设我们有三个任务:时钟显示,按键扫描,和工作状态显示。
1. 定义一个上面定义的那种结构体变量复制内容到剪贴板代码:/******************************************************************** ******************* Variable definition********************************************************************* *****************/static TASK_COMPONENTS TaskComps[] ={{0, 60, 60, TaskDisplayClock}, // 显示时钟{0, 20, 20, TaskKeySan}, // 按键扫描{0, 30, 30, TaskDispStatus}, // 显示工作状态// 这里添加你的任务。
};在定义变量时,我们已经初始化了值,这些值的初始化,非常重要,跟具体的执行时间优先级等都有关系,这个需要自己掌握。