第三章 C/C++语言基础
C/C++语言是国际上广泛流行的计算机高级语言。在进行绝大多数的硬件开发时,均使用C/C++语言,Arduino也不例外。使用Arduino时需要有一定的C/C++基础,由于篇幅有限,在此仅对C/C++语言基础进行简单介绍。 本章将分为如下9个小节: - 3.1 数据类型
- 3.2 运算符
- 3.3 表达式
- 3.4 数组
- 3.5 字符串
- 3.6 注释
- 3.7 顺序结构
- 3.8 选择结构
- 3.9 循环结构
3.1 数据类型在C/C++语言程序中,对所有数据都必须指定其数据类型。数据有常亮和变量之分。需要注意的是,Arduino中的部分数据类型与计算机中的有所不同。 1. 常量 在程序运行过程中,其值不能改变的量称为变量。常量可以是字符,也可以是数字,通常使用以下语句定义常量。 #define 常量名 常量值 如在Arduino核心库中已经定义的常量PI,即是使用以下语句定义的。 #define PI 3.1415926535897932384626433832795 2. 变量 程序中可变的值称为变量。其定义方法是: 类型 变量名; 例如,定义一个整形变量i的语句是: int i; 可以在定义变量的同时为其赋值,也可以在定义之后,再对其赋值,例如: int i = 88; 和以下的两条语句是一样的效果,这两者是等效的。 int i; i = 95; (1) 整型 整型即整数类型。Arduino可使用的数据类型及其取值范围如表3.1.1所示。 类型 | 关键字(简写) | 占用内存 | 取值范围 | | | | | | | | | | | | | | | | | | | | -9223372036854775808 ~ 9223372036854775807 | | uint64_t(unsigned long long) | | |
表3.1.1 数据类型表 (2) 浮点型 浮点数其实就是平常所说的实数。在Arduino中有float和double两种浮点类型,在ESP32作为主控芯片的Arduino开发板上,float类型占用4字节内存空间,double类型占用8字节内存空间。但在某些Arduino开发板中,这两种类型占用内存空间可能存在差异。 浮点型数据的运算较慢且有一定误差,因此,通常会把浮点型转换为整型来处理相关运算。比如,9.8cm,通常会换算成98mm来计算。 (3) 字符型 字符型,即为char类型,其占用1字节的内存空间,主要用于存储字符变量。在存储字符时,字符需要用单引号引用,如下所示: char g_char = ’A’; 字符都是以数字形式存储在char类型变量中的,数字与字符的对应关系即平常说的 ASCII码表,如下图所示。 (4) 布尔型 布尔型变量即boolean类型。它的值只有两个:false(假)和true(真)。Boolean类型会占用1字节的内存空间。
3.2 运算符 C/C++语言中有多种类型的运算符,常见运算符如表3.2.1所示: 表3.2.1 运算符表
3.3 表达式 通过运算符将运算对象连接起来的式子称为表达式,如1 + 2、a – b、3 < 4等。
3.4 数组 数组是由一组具有相同数据类型的数据构成的集合。数组概念的引入,使得在处理多个相同类型的数据时程序更加清晰和简洁。 定义方式如下: 数据类型 数组名称[数组元素个数]; 例如,定义一个有5个int型元素数组的语句为: int a[5]; 如果要访问一个数组中的某个元素,则需要使用以下语句。 数组名称[下标] 需要注意的是,数组下标是从0开始编号的。例如,将数组a中的第一个元素赋值为1的语句为: a[0] = 1; 除了使用以上方法对数组赋值外,也可以在数组定义时对数组进行复制,如下语句: int a[5] = {1, 2, 3, 4, 5}; 或者使用以下语句实现,是同等效果。 int a[5]; a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4; a[4] = 5;
3.5 字符串 字符串的定义方式有两种,一种是以字符型数组方式定义,另一种是使用String类型定义。 以字符型数组方式定义的语句为: char 字符串名称[字符个数]; 使用字符型数组方式定义的字符串,其使用方法跟数组的使用方式一致,有多少个字符便占用多少字节的存储空间。 而在Arduino中,大多数情况下是使用String类型来定义字符串,该类型提供了一些操作字符串的成员函数,使得字符串使用起来更为灵活。定义语句是: String 字符串名称; 具体使用,如下语句 String abc; abc = ”Arduino”; 或者使用如下语句,实现同样的效果。 String abc = ”Arduino”; 相较于数组形式的定义方式,使用String类型定义字符串会占用更多的存储空间。
3.6 注释 “/*”与“*/”之间的内容以及“//”之后的内容均为程序注释,使用他们可以更好地管理代码。注释不会被编译到程序中,因此不影响程序的运行。 为程序添加注释的方式有两种。 ① 单行注释,语句为 // 注释内容 ② 多行注释,语句为 /* 注释内容1 注释内容2 …… */
3.7 顺序结构顺序结构是三种基本结构之一,也是最简单的一种流程结构,它采用自上而下的方式逐条执行各语句。简易顺序结构如下图所示: 图3.7.1 顺序结构图 框中的步骤1、步骤2和步骤3都是按顺序执行的,先执行步骤1,然后再执行步骤2,最后执行步骤3。
3.8 选择结构选择结构,又称分支结构,可以控制程序的部分流程是否被执行,或者是从多条执行路径种选择一条来执行。在C语言中有两种选择语句:① if语句,用来实现两个分支的选择结构 ② switch语句,用来实现多分支的选择结构。 选择结构if,具体用法如下表所示: | | if (表达式) { if (表达式) {语句} } else {语句} | if (表达式) {语句} else if (表达式) {语句} else {语句} |
表3.7.1 选择结构if用法 选择结构switch,具体使用格式如下: switch (整型表达式) { case 整型常量表达式1: [语句1; break;] case 整型常量表达式2: [语句2; break;] case 整型常量表达式3: [语句3; break;] … [default: } 在程序运行时,首先会计算整型表达式的值,然后用该值与后面的所有case标签进行一一匹配(即查看该值是否与case标签的表达式的值相同)。如果有匹配的case标签,则从该case标签起,执行后续的语句,直至遇到break语句为止。如果没有匹配到case标签,则从default标签起,执行后续的语句,直到遇到break为止。 这里特别需要注意:① case后带的表达式一定要是常数,并且是整型。②在语句后面通常是有break关键字。③ 最后一般有default,即前面case没有一个符合的情况,就会调到default里执行。虽然说语法上可以允许没有default,但是为了完整,建议是需要的。 那么if和switch这两种选择结构有啥区别呢? if 语句比较适用在对比条件比较复杂的且分支比较少的情况下使用;switch语句则是适用在对比条件比较简单且分支比较多的情况下使用;正常情况下,先考虑能不能用switch语句,假如不满足使用需求,则使用if语句。当然,不管黑猫白猫捉到老鼠的就是好猫,能实现效果即可。
3.9 循环结构循环结构就是重复执行一个语句块,直到不满足某个条件为止。在C语言中有三种循环语句:① while语句 ② do while语句 ③ for语句 while语句也称while循环,具体使用格式如下: while (表达式) 语句 while语句根据小括号内表达式的值来决定是否执行语句,当表达式的值为假时,循环结束,语句不会被执行;假如表达式的值为真,语句被执行,然后会再次判断表达式的值,如此反复,直至表达式的值为假。 do while语句也称do while循环,具体使用格式如下: do 语句 while (表达式) 从结构上,由“do”关键字开头,紧接着是语句也就是循环体了,最后是while关键字和表达式。do while语句是先执行循环体,然后再检查条件是否成立,若成立,再执行循环体,这就是跟while语句不同。 for语句,相对前面两个循环语句复杂一点,具体使用格式如下: for (表达式1; 表达式2; 表达式3) 语句 相比前面的while和do while语句,for语句的表达式有三个,表达式之间用‘;’隔开,这三个表达式的作用和执行时期是不一样的,具体情况如下表: 表3.9.1 for语句表达式情况 具体执行流程:在for语句被执行前,首先会执行表达式1,然后再检查表达式2的值:假如为假,不执行循环体,结束for语句;假如为真,则执行循环体语句。执行完循环语句后,再去执行表达式3,并再次去检查表达式2的值,如此反复,直到表达式2的值为假,结束for语句。 这三个循环语句,哪种情况用哪个好呢? 如果程序中固定了循环的次数,那么就可以采用for语句。如果程序中必须执行一次程序,那么就可以使用do while语句。除了以上两种情况,就可以使用while语句。
|