0、前言
本专栏为个人备考软考嵌入式系统设计师的复习笔记,未经本人许可,请勿转载,如发现本笔记内容的错误还望各位不吝赐教(笔记内容可能有误怕产生错误引导)。
1、嵌入式系统开发与设计
1.1嵌入式应用程序的生成与加载
嵌入式软件开发的特点:
- 需要交叉编译工具
- 通过仿真手段进行测试
- 开发板是中间目标机
- 可利用的资源有限
- 需要与硬件打交道
嵌入式软件开发的挑战:
- 软硬件协同设计
- 嵌入式操作系统
- 代码优化
- 有限的I/0功能
嵌入式系统开发最大特点:
- 软硬件综合开发。
- 嵌入式产品是软硬件的结合体
- 软件针对硬件开发、固化,不能进行任意修改
嵌入式软件开发模式通常是包括三种:
- 本机开发
- 交叉开发:见下图,提供了丰富的开发工具,可以及时调试与修改程序。
- 模拟开发:在宿主机上面模拟了一个目标机的环境
宿主机与目标机:
下载与运行:
嵌入式软件开发流程:
1.2解释程序/编译程序
●解释程序
也称解释器;直接解释执行源程序,或者将源程序翻译成某种中间代码后再加以执行。
●编译程序
也称编译器,将源程序翻译成目标语言程序,然后在计算机上运行日标程序。
●两者的根本区别
编译方式下,机器上运行的是与源程序等价的目标程序,源程序和编译程序都不再参与目标程序的执行过程。
解释方式下,解释程序和源程序(或某种等价表示)要参与到程序的运行过程中,运行程序的控制权在解释程序。
即:解释方式,翻译程序不生成独立的日标程序,而编译方式则生成独立保持的日标程序。
1.3 编译器工作的过程
●词法分析阶段
是编译过程的第一阶段,其任务是对源程序从前到后(从左到右)逐个字符扫描,从中识别出一个个“单词”符号。
词法分析过程的依据是语言的词法规则,即描述“单词”结构的规则。
●语法分析阶段
其任务是在词法分析的基础上,根据语言的语法规则将单词符号序列分解成各类语法单位。通常语法分析是确定整个输入串是否构成一个语法上正确的程序。一般来说,通过编译的程序,不存在语法上的错误。
●语义分析阶段
其任务主要检查源程序是否包含静态语义错误,并收集类型信息供后面的代码生成阶段使用。语义分析的一个主要工作是进行类型分析和检查。
●中间代码生成
其任务是根据语义分析的输出生成中间代码。
●目标代码生成
是编译器工作的最后一个阶段。其任务是把中间代码变换成特定机器上的绝对指令代码、可重定位的指令代码或汇编指令代码。本阶段与具体机器密切相关。
●符号表管理
符号表的作用是记录源程序中各个符号的必要信息,以辅助语义的正确性检查和代码生成,在编译过程中需要对符号表进行快速有效地查找、插入、修改和删除等操作。
2、程序设计语言
2.1程序设计语言
2.1.1常见编程语言分类
Fortran语言(科学计算,执行效率高)
Pascal语言(为教学而开发的,表达能力强,Delphi)
C语言(指针操作能力强,高效)
Lisp语言(函数式程序语言,符号处理,人工智能)
C++语言(面向对象,高效)
Java语言(面向对象,半解析半执行中间代码,跨平台)C#语言(面向对象,中间代码,.Net)
Prolog语言(逻辑推理,简洁性,表达能力,数据库和专家系统)
Python语言(一种脚本语言)HTML
2.1.2程序语言的成分
数据是程序操作的对象,具有以下的属性:
常量 变量 全局量 局部量
数据名称:由用户通过标识符命名
数据类型:说明数据占用内存的大小和存放形式存储类别:说明数据在内存中的位置和生存期
作用域:说明可以使用数据的代码范围
生存期:说明数据占用内存的时间范围
程序设计语言的基本成分包括:数据、运算、控制和传输
数据类型:
- 基本类型:整形、字符型、实型、布尔型
- 特殊类型:空类型(void)
- 用户定义类型:枚举类型
- 构造类型:数组、结构、联合
- 指针类型:type*
- 抽象类型:类类型
数据类型转换规则:char,short到int到unsigned到long,float到double
运算成分:
指明允许使用的运算符号及运算规则,运算符号要规定优先级和结合性,大多数高级程序语言的基本运算包括了:
- 算术运算
- 关系运算
- 逻辑运箅
- 位运箅
控制成分:
三种基本逻辑结构
- 顺序结构:是一种线性有序的结构,由一系列依次执行的语句或模块构成
- 循环结构:是由一个或几个模块构成,程序运行时重复执行,直到满足某一条件为止
- 选择结构:是根据条件成立与否选择执行路径的结构
传输成分:
传值/传址 :
- 传值调用(有去无回):实际上重新复制了一个副本给形参不改变调用函数实参变量的内容
- 传址调用(有去有回):将实参地址给形参将改变调用函数实参变量的内容
表达式:
前缀表达式(+ab)
中缀表达式(a+b)
后缀表达式(ab-) 逆波兰式
高级程序设计语言:
解析程序基本原理:
解释程序是另一种语言处理程序,在词法、语法和语义分析方面与编译程序的工作原理基本相同。
但在运行用户程序时,它直接执行源程序或源程序的内部形式。因此,解释程序与编译程序最大的区别就是不产生源程序的目标程序
解释程序通常可分为两部分
- 分析部分,包括通常的词法分析、语法分析和语义分析程序,经分析后把源程序翻译成
- 中间代码。
- 解释部分,用来对第一部分所产生的中间代码进行解释执行。
实现的三种方式:
直接被解释执行
先将源程序翻译成某种中间代码形式,然后再对中间代码进行解释,根据中间代码级别的方式不同,分为B、C两种方式见下图:
2.2面向过程的语言
c语言的基本概念:
C预处理:
预处理代码例程:
#include <stdio.h>
#define square(x) ((x)*(x))
#define square_1(x) (x *x)
int main(void)
{
printf("'square 5+4 is %d\n", square(5+4));%81
printf("square_1 5+4 is %d\n", square_1(5+4));%26
return 0;
}
预定义宏:
宏名的书写由标识符与两边各两条下划线构成
基本数据类型:
存储管理:
函数调用过程:
变量的存储与作用域:
/*全局变量,因定地址,其它源文件可见*/ int global_static; /静态全局变量,因定地址,但只在本文件中可见"/ static int file_static; /*函致参数,位于栈帧当中,动态创建,动态释放"/ int foo (int auto_program) { /*静态局部变量,因定地址,只在本函数中可见"/ static int func_static; /普通局部变量,位于栈顿当中,只在本函数中可见"/ int auto_i, auto _a[10}; /动态申请的内存空间,位于堆当中"/ double *auto_d=malloc(sizeof(double)"5); reuturn auto i; }
2.3面向对象的语言
面向对象编程(Object-Oriented Programming,简称OOP)是一种程序设计范式,通过将数据项和操作封装在对象中来组织和管理代码。下面是面向对象编程的一般流程:
分析问题:
- 首先,需要对解决的问题进行分析和理解。明确问题的需求和功能,识别需要解决的实体和行为。
设计类:
- 根据问题的需求和实体的特征,设计表示问题域中实体的类。类包括属性(数据项)和方法(操作),用于描述实体的状态和行为。
定义类:
- 在编程语言中定义类,描述类的属性和方法。属性用于存储对象的状态,方法用于操作对象。
创建对象:
- 根据类的定义,创建类的实例(对象)。对象是类的具体实体,可以访问类的属性和方法。
封装:
- 封装是指将数据(属性)和行为(方法)封装在对象内部,隐藏对象的内部实现细节,提供接口供外部访问和操作。
继承:
- 如果存在类之间的共性和关系,可以使用继承机制构建类之间的层次结构。子类(派生类)可以继承父类(基类)的属性和方法,实现代码的重用和扩展。
多态:
- 多态是面向对象编程的重要特征,通过多态可以实现同一接口的不同实现。使用多态可以提高代码的灵活性和可维护性。
实现功能:
- 根据类和对象的定义,实现程序的功能,通过对象之间的交互实现问题的解决。
测试和调试:
- 编写好代码后,需要对程序进行测试和调试,确保程序的功能正确并且没有错误。
优化和扩展:
- 根据需求,可以对程序进行优化和扩展。可以添加新的类、方法或属性,提高程序性能和可扩展性。
以上是面向对象编程的一般流程,通过遵循这个流程,可以更好地设计、构建和维护面向对象的程序,提高代码的可读性、可维护性和可扩展性。
c++的基本概念:
Peter Coad和Edward Yourdon提出用下面的等式来识别面向对象方法,采用这四个概念开发的软件系统是面向对象的。这个考的不多,图里面的掌握就差不多了。
在C++中,多态(polymorphism)、重载(overloading)和覆盖(overriding)是面向对象编程中常用的概念,用于实现不同类型的对象之间的灵活性和可复用性。以下是它们的概念及区别:
多态(Polymorphism):
- 多态是指同一个函数名可以具有不同的行为表现形式的能力。在C++中,多态分为静态多态(编译时多态)和动态多态(运行时多态):
- 静态多态:通过函数的重载(overloading)和运算符重载(operator overloading)来实现,编译器在编译时根据函数调用的参数类型或个数确定具体调用的函数。
- 动态多态:通过虚函数和继承关系(inheritance)实现,使用基类的指针或引用指向派生类对象,在运行时确定调用的函数。
重载(Overloading):
- 重载是指在同一作用域内允许使用相同名称但参数列表不同的函数。在C++中,函数重载可以根据函数参数的类型、个数或顺序来区分同名函数,从而实现多态。
- 重载函数的返回类型不是区分函数的标准。函数重载可以让开发者通过命名相似的函数来增加代码的可读性和可维护性。
覆盖(Overriding):
- 覆盖是指在派生类中重新定义基类中已有的虚函数,以实现不同的行为。通过继承和重写基类中的虚函数,派生类可以提供自己的实现逻辑。
- 子类中的覆盖函数的函数签名(函数名、参数列表、常量性等)必须与基类中的虚函数一致,否则不会形成覆盖。
在C++中,继承是一种面向对象编程的重要概念,允许一个类(称为派生类)基于另一个类(称为基类)的定义来构建。通过继承,派生类可以继承基类的属性和方法,同时可以添加自己的属性和方法,从而实现代码的重用和扩展。下面以一个简单的示例说明继承的概念:
#include <iostream>
using namespace std;
// 基类
class Animal {
public:
void eat() {
cout << "Animals eat food" << endl;
}
};
// 派生类
class Dog : public Animal {
public:
void bark() {
cout << "Dogs bark" << endl;
}
};
int main() {
Dog myDog;
myDog.eat(); // 派生类对象可以调用从基类继承的方法
myDog.bark(); // 派生类对象也可以调用自己添加的方法
return 0;
}
在上面的例子中,我们定义了一个基类Animal和一个派生类Dog。派生类Dog通过关键字public
继承了基类Animal。派生类Dog可以访问基类Animal中的eat()
方法,同时也可以添加自己的方法bark()
。在main()
函数中,我们创建了一个Dog类的对象myDog,并通过该对象调用了继承自基类的eat()
方法和派生类自己的bark()
方法。
继承的优势在于可以实现代码的重用和扩展,减少重复代码的编写,并且可以通过多层次的继承建立类之间的层次结构。继承也为多态和代码复用提供了基础,是面向对象编程中的重要概念之一。
尾言
本专栏我总结了大量的思维导图,但是因为思维导图太大与CSDN的排版不匹配,故我会把每篇博文绘制的思维导图上传到我的资源里,有需要的自取,我会设置为0积分下载的,创作不易还望各位大佬点赞支持一下谢谢