51单片机C语言简介81_第1页
51单片机C语言简介81_第2页
51单片机C语言简介81_第3页
51单片机C语言简介81_第4页
51单片机C语言简介81_第5页
已阅读5页,还剩97页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第7章 51单片机C语言简介 7.1 C语言的根本知识 7.2 C51程序设计的根本语法 7.3 C51程序设计 7.4 函数 7.5 模块化程序设计 7.6 C51编程实例 7.1 C语言的根本知识 7.1.1 C语言的特点与程序结构 以前计算机的系统软件主要是用汇编语言编写的,对于单片机应用系统来说更是如此。由于汇编语言程序的可读性和可移植性都较差,采用汇编语言编写单片机应用系统程序的周期长,而且调试和排错也比较困难。为了提高编制计算机系统和应用程序的效率,改善程序的可读性和可移植性,最好采用高级语言编程。C语言既具有一般高级语言的特点,又能直接对计算机的硬件进行操作,并且采用C语言编写的

2、程序能够很容易地在不同类型的计算机之间进行移植。与其它计算机高级语言相比,C语言具有它自身的特点: 1语言简洁,使用方便灵活。 2可移植性好。 3表达能力强。 4可进行结构化程序设计。 5可以直接操作计算机硬件。 6生成的目标代码质量高 。 尽管C语言具有很多的优点,但和其它任何一种程序设计语言一样,也有其自身的缺点,如不能自动检查数组的边界,各种运算符的优先级别太多,某些运算符具有多种用途等。 C语言程序是由假设干个函数单元组成的,每个函数都是完成某个特殊任务的子程序段。组成一个程序的假设干个函数可以保存在一个源程序文件中,也可以保存语言源程序文件的文件名由程序设计人员根据某种俗成规那么自己

3、确定,其扩展名统一为“.C。如A1-1.C、A2-1.C。 C语言程序的开始局部通常是预处理命令,如程序中通常遇到的include命令。这个预处理命令通知编译器在对程序进行编译时,将所需要的头文件读入后再一起进行编译。一般在“头文件中包含有程序在编译时的一些必要的信息,通常C语言编译器都会提供假设干个不同用途的头文件。头文件的读入是在对程序进行编译时才完成的。 C语言程序是由函数所组成的。一个完整的C语言程序应包含一个主函数main和假设干个其它功能的函数。函数之间可以相互调用,但main函数只能调用其它的功能函数,而不能被其它函数所调用。功能函数可以是C语言编译器提供的库函数,也可以由用户按

4、实际需要自行编写的函数。不管main函数处于程序中的什么位置,程序总是从main函数开始执行。一个函数必须预先定义或声明后才能调用。 函数定义或声明位于源程序的预处理命令之后的开始位置。函数定义局部包括有函数的存储类型、返回值数据类型、函数名、形式参数说明等,函数名后面必须跟一个圆括弧,形式参数说明在圆括弧内进行。函数也可以没有形式参数,如main( )。函数的位置比较自由。可以由程序设计人员安排在函数定义后的任意位置。函数由函数名和一对花括弧“组成,在“里面的内容就是函数体,如果一个函数有多个“,那么最外面的一对“为函数体的范围。 函数体的内容为假设干条语句,一般有两类语句,一类为说明语句,

5、用来对函数中将要用到的变量进行定义;另一类为执行语句,用来完成一定的功能或算法处理。有的函数体仅有一对“,其中既没有变量定义语句,也没有执行语句,这也是合法的,称为“空函数。 C语言源程序可以采用任何一种编辑器来编写,既可以是windows环境下的编辑器,如记事本NOTEPAD或写字板WORDPAD,也可以是DOS环境下的编辑器,如EDIT或PE等。C语言程序的书写格式十分自由。一条语句可以写成一行,也可以写成几行;还可以在一行内写多条语句;但是需要注意的是,每条语句都必须以分号“;作为结束符。 另外,C语言区分大小写字母,C语言编译器在对程序进行编译时,对于程序中同一个字母的大小写作为不同的

6、变量来处理。虽然C语言程序不要求具有固定的格式,但我们在实际编写程序时还是应该遵守一定的规那么,一般应按程序的功能以“缩格形式来写程序,同时还应在适当的地方加上必要的注释。注释对于比较大的程序来说是十分重要的,这有利于修改与读懂程序。 C语言本身没有输入输出功能,C语言程序的输入和输出是通过函数调用来实现的。Franklin C51编译器提供的输入输出库函数 scanf和 printf是通过 8051单片机的串行口实现的,在程序中使用这种输入输出库函数之前必须先对8051单片机的串行口进行初始化。但是对于单片机应用系统来说,由于具体要求的不同,应用系统的输入输出方式多种多样,不可能一律采用串行

7、口作输入和输出。因此应该根据实际需要,由应用系统的研制人员自己来编写满足特定需要的输入输出函数,这一点对于单片机应用系统的开发研制人员来说是十分重要的。 7.1.2 C语言的标识符和关键字 C语言的标识符是用来标识源程序中某个对象名字的。这些对象可以是函数、变量、常量、数组、数据类型、存储方式、语句等。一个标识符由字符串、数字和下划线等组成,第一个字符必须是字母或下划线,通常以下划线开头的标识符是编译系统专用的,因此在编写C语言源程序时一般不要使用以下划线开头的标识符,而将下划线用作分段符。C51编译器规定标识符最长可达255个字符,但只有前面32个字符在编译时有效,因此在编写源程序时标识符的

8、长度不要超过 32个字符。程序中对于标识符的命名应当简洁明了,含义清晰,便于阅读理解,如用标识符“max表示最大值,用“TIMER0表示定时器0等。 关键字是一类具有固定名称和特定含义的特殊标识符,又称为保存字。在编写C语言源程序时一般不允许将关键字另作别用,换句话说就是对于标识符的命名不要与关键字相同。在C语言中,ANSI C标准一共规定了32个关键字,表 7.1按用途列出了 ANSI C标准的关键字。表 7.1 ANSI C标准的关键字关键字 用 途 说 明 autobreakcasecharconstcontinue defaultdodoubleelseenumexternfloatf

9、orgotoifintlongregisterreturnshortsignedsizeofstaticstructswitchtypedefunionunsignedvoidvolatilewhile存储类说明程序语句程序语句数据类型说明存储类型说明程序语句程序语句程序语句数据类型说明程序语句数据类型说明存储种类说明数据类型说明程序语句程序语句程序语句数据类型说明数据类型说明存储种类说明程序语句数据类型说明数据类型说明运算符存储种类说明数据类型说明程序语句数据类型说明数据类型说明数据类型说明数据类型说明数据类型说明程序语句用以说明局部变量退出最内层循环switch语句中的选择项单字节整型数或

10、字符型数据在程序执行过程中不可能修改的变量值转向下一个循环switch语句中的失败选择项构成dowhile循环结构双精度浮点数构成 ifelse选择结构枚举在其它程序模块中说明了的全局变量单精度浮点数构成for循环结构构成goto转移结构构成ifelse选择结构基本整型数长整型数使用CPU内部寄存器的变量函数返回短整型数有符号数,二进制数据的最高位为符号位计算表达式或数据类型的字节数静态变量结构类型数据构成switch选择结构重新进行数据类型定义联合数据类型无符号数据无符号数据说明该变量在程序执行中可被隐含地改变构成while和dowhile循环结构 关键字 用 途 说 明bitsbitsfr

11、sfr16databdataidatapdataxdatacodeinterruptUsingreetrant位标量声明位标量声明特殊功能寄存器声明特殊功能寄存器声明存储器类型声明存储器类型声明存储器类型说明存储器类型说明存储器类型说明存储器类型说明中断函数说明寄存器组定义再入函数声明声明一个位标量或位类型的函数声明一个可位寻址变量声明一个特殊功能寄存器(8位)声明一个16位的特殊功能寄存器直接寻址的8051内部数据存储器可位寻址的8051内部数据存储器间接寻址的8051内部数据存储器“分页”寻址的8051外部数据存储器8051外部数据存储器8051程序存储器定义一个中断函数定义8051工作寄

12、存器组定义一个再入函数C51编译器除了支持ANSI C标准关键字以外,还扩展了如表7.2所示的关键字: 表7.2C51编译器的扩展关键字7.1.3 单片机C51程序的编译连接与调试 Franklin C51交叉编译器是专为8051系列单片机设计的C语言编译器,它能在IBM PC及其兼容机上运行,使用非常方便。为了保证编译器能正常工作,PC机应具有512K以上的内存、一个软盘驱动器、一个硬盘,采用MSDOS 3.0以上版本的操作系统。Franklin C51以软件包的形式提供,软件包中主要有C51交叉编译器、A51交叉汇编器、L51连接定位器、OHS51代码转换器和 dScope一51软件仿真调

13、试器以及其它一些实用软件程序。如果在PC机的硬盘C:上安装C51编译器,在安装之前应对PC机的配置文件CONFIG.SYS和自动批处理文件AUTOEXEC.BAT作如下修改: CONFIG.SYS: FIELS 20 BUFFER 20 AUTOEXEC.BAT: SET C51LIB=C:C51LIB SET C51INC C:CSIINC SET PATH=C:C51BIN 这样修改之后,C51编译器会当头文件不在当前目录时,能从C:C51INC子目录中找到头文件;L51连接器会自动为所有的编译模式及算术尤其是浮点运算功能从C:C51LIB于目录中找到所需要的库文件。 C51编译器可根据不

14、同的硬件环境由4个文件做出修改。以下配置文件包括在C51软件包中: STARTUP.A51:C51编译器的启动程序,所有的栈指针和存贮器,只要需要,将被初始化。 INT.A51:在文件中已明确初始化了的变量作初始化。如果系统装了“看门狗,该文件可包含附加的“看门狗刷新。 PUTCHAR.C:函数“printf、“puts等的字符输出核心程序,该程序可根据用户硬件加以修改如LCD显示。 GETKEY.C:函数“getchar、“scanf等的字符输入核心程序,该程序可根据硬件加以修改如矩阵键盘 所有文件都包含在C运行库中,因此,不能在连接时指定调用。如果用户改变一个文件,可将其编译后与其它目标文

15、件一起连接,因而不必改动运行库。库中原文件自动忽略。 例:L51 MYMODUL1.OBJ,MYMODUL2.OBJ ,STARTUP.OBJ,PUTCHAR.OBJ 上例将用户建立的STARTUP.OBJ和PUTCHAR.OBJ连接起来。 用C语言编写的程序必须通过编译和连接之后,才能生成可执行代码。C51编译器由命令“C51启动,例如以EXI2.C为文件名的程序编译命令如下; C51 EXI2.C CODE DEBUG回车 C51是编译器启动命令,EXI2.C是程序文件名,CODE和DEBUG是编译控制指令。输入完命令后回车,即可进人编译过程。如果编译过程中未发现错误,屏幕上会显示出: C

16、51 COMPILATION COMPILETE, 0 WARINGS, 0 ERRORS 并产生列表文件 EXI2.LST和目标文件 EXI2.OBJ。如果编译中发现任何错误,那么不产生目标文件,而将所有的错误信息都在列表文件中表示出来。编译控制指令CODE使列表文件的后面附加一个汇编语言文件。编译控制指令DEBUG使目标文件中包含有进行源程序调试时需要的各种符号信息。目标文件中还包含有可再定位的目标码,以供 L51连接器作进一步的处理。C51编译器提供了许多不同控制指令可以完成各种编译控制功能。7.2 C51程序设计的根本语法 C语言是一种程序设计语言,采用C语言进行程序设计时,需要遵循一

17、定的语法规那么。 7.2.1 C语言的数据类型 C语言的数据结构是以数据类型出现的,数据类型可分为根本数据类型和复杂数据类型,复杂数据类型由根本数据类型构造而成。C语言中的根本数据类型有char,int,short,long,float和double。对于C51编译器来说,short型与int型相同, double型与float型相同。分别说明如下: 1 char 字符类型。有 signed char和 unsigned char之分,默认值为 signed char。对于 signed char型数据,其字节中的最高位表示该数据的符号,“0表示正数,“l表示负数。负数用补码表示。所能表示的数

18、值范围是 -128127;unsigned char型数据,是无符号字符型数据,其字节中的所有位均用来表示数据的数值,所表示的数值范围是 0255。 2 int 整型。有signed int和unsigned nit之分,默认值为signed int。signed int是有符号整型数,字节中的最高位表示数据的符号,“0表示正数,“1表示负数。所能表示的数值范围是 -32768+32767。unsigned int是无符号整型数,所表示的数值范围是065535。 3 long 长整型。有signed long和unsigned long之分,默认值为signed long。它们的长度均为四个字

19、节。singed long是有符号的长整型数据,字节中的最高位表示数据的符号,“ 0表示正数,“1表示负数。数值的表示范围是2147483648 2147483647; unsigned long是无符号长整型数据,数值的表示范围是04294967295。 4float 浮点型。它是符合IEEE754标准的单精度浮点型数据,在十进制中具有7位有效数字。float型数据占用四个字节 2位二进制数。 需要指出的是,对于浮点型数据除了有正常数值之外,还可能出现非正常数值。根据IEEE标准,当浮点型数据取以下数值16进制数时即为非正常值:FFFFFFFFH非数NaN;7F800000H正溢出INF;F

20、F800000H负溢出INF; 另外,由于8051单片机不包括捕获浮点运算错误的中断向量,因此必须由用户自己根据可能出现的错误条件用软件来进行适当的处理。 5* 指针型。指针型数据不同于以上四种根本数据类型,它本身是一个变量,但在这个变量中存放的不是普通的数据而是指向另一个数据的地址。指针变量也要占据一定的内存单元,在C51中指针变量的长度一般为3个字节。指针变量也具有类型,其表示方法是在指针符号“*的前面冠以数据类型符号。如 char *Pointl;表示 Pointl是一个字符型的指针变量。指针变量的类型表示该指针所指向地址中数据的类型。使用指针型变量可以方便地对8051单片机的各局部物理

21、地址直接进行操作。 6bit 位标量。这是C 51编译器的一种扩充数据类型,利用它可定义一个位标量,但不能定义位指针,也不能定义位数组。 7sfr 特殊功能存放器。这也是C 51编译器的一种扩充数据类型,利用它可以访问8051单片机的所有内部特殊功能存放器。sfr型数据占用一个内存单元,其取值范围0255。 8sfr16 16位特殊功能存放器。它占用两个内存单元,取值范围是065535。 9sbit 可寻址位。这也是C51编译器的一种扩充数据类型,利用它可以访8051单片机内部RAM中的可寻址位或特殊功能存放器中的可寻址位。 在C语言程序中的表达式或变量赋值运算中,有时会出现运算对象的数据不一

22、致的情况,C语言允许任何标准数据类型之间的隐式转换。隐式转换按以下优先级别自动进行: bit char int long float signed unsigned 转换时由低向高进行,而不是数据转换时的顺序。一般来说,如果有几个不同类型的数据同时参加运算,先将低级别类型的数据转换成高级别类型,再作运算处理,并且运算结果为高级别类型数据。 C51编译器除了能支持以上这些根本数据之外,还能支持一些复杂的构造型数据,如结构类型、联合类型等。 7.2.2 常量 常量是在程序执行过程中其值不能改变的量。常量的数据类型有整型、浮点型、字符型和字符串型等,C51编译器还扩充了一种位bit标量。分别说明如下

23、: 1整型常量 整型常量就是整型常数,可表示为以下几种形式:十进制整数;十六进制整数:以 0X开头的数是十六进制数,ANSI C标准规定十六进制数的数字为09,再加字母af;长整数:在数字后面加一个字母L就构成了长整数。 2浮点型常量 浮点型常量有十进制表示形式和指数表示形式。 十进制表示形式又称定点表示形式,由数字和小数点组成。如 0.3141、31.41、314.1及0.0都是十进制数表示形式的浮点型常量。 在这种表示形式中,如果整数或小数局部为0可以省略不写,但必须有小数点。 指数表示形式为: 数字数字e 数字 其中,中的内容为可选项,可有可无,但其余局部必须有。 3字符型常量 字符型常

24、量是单引号内的字符,如a、b等。对于不可显示的控制字符,可以在该字符前面加一个反斜杠字符“组成专用转义字符。利用转义字符可以完成一些特殊功能和输出时的格式控制。 4字符串型常量 字符串型常量由双引号“内的字符组成。当双引号内的字符个数为0时,称为空串常量。需要注意的是,字符串常量首尾的双引号是界限符,当需要表示双引号字符串时,可用转义字符来表示为:“。 如:“I say:“goodbye!字符串为I say:“goodbye! 另外,C语言将字符串常量作为一个字符类型数组来处理,在存储字符串常量时,要在字符串的尾部加一个转义字符0作为该字符串常量的结束符。因此不要将字符常量与字符串常量混淆。5

25、位标量 这是C51编译器的一种扩充数据类型。位标量用关键字“bit来定义,它的值是一个二进制位。一个函数中可以包含“bit类型的参数,函数的返回值也可为“bit型。 另外,不能定义位指针,也不能定义位数组。7.2.3 变量及其存储模式 和常量相比,变量是另一种量,在程序执行过程中其值能不断变化。每一个变量都必须有一个标识符作为它的变量名。在使用一个变量之前,必须先对该变量进行定义,指出它的数据类型和存储模式,以便编译系统为它分配相应的存储单元。在C51中对变量进行定义的格式如下: 存储种类数据类型存储器类型变量名表; 其中,“存储种类和“存储器类型是可选项。变量的存储种类有四种:自动auto、

26、外部extern、静态static和存放器register。在定义一个变量时如果省略存储种类选项,那么该变量将为自动auto变量。 定义一个变量时除了需要说明其数据类型之外,C51编译器还允许说明变量的存储器类型。 Franklin C51对于每个变量可以准确地赋予其存储器类型,从而可使之能够在单片机系统内准确地定位。 定义变量时如果省略“存储器类型选项,那么按编译模式SMALL、COMPACT或LARGE所规定的默认存储器类型确定变量的存储区域,不能位于存放器中的参数传递变量和过程变量也保存在默认的存储器区域。C51编译器的三种存储器模式默认的存储器类型对变量的影响如下: 1. SMALL

27、变量被定义在 8051单片机的内部数据存储器中,因此对这种变量的访问速度最快。另外,所有的对象,包括堆栈,都必须嵌入内部数据存储器,而堆栈的长度是很重要的,实际栈长取决于不同函数的嵌套深度。 2. COMPACT 变量被定义在分页外部数据存储器中,外部数据段的长度可达256字节。这时对变量的访问是通过存放器间接寻址MOVX Ri进行的,堆栈位于8051单片机内部数据存储器中。采用这种编译模式时,变量的高 8位地址由 P2口确定。因此,在采用这种模式的同时,必须适当改变启动程序 STARTUPA51中的参数:PDATASTART和PDATALEN;用L51进行连接时还必须采用连接控制命令PDAT

28、A来对P2口地址进行定位,这样才能确保P2口为所需要的高8位地址。 3. LARGE 变量被定义在外部数据存储器中最大可达64K字节,使用数据指针DPTR来间接访问变量。这种访问数据的方法效率是不高的,尤其是对于2个或多个字节的变量,用这种数据访问方法相当影响程序的代码长度。另外一个不方便之处是这种数据指针不能对称操作。 需要特别指出的是,变量的存储种类与存储器类型是完全无关的。例如: static unsigned char data x ;* 在内部数据 存储器中定义一个静态无符号字符型变量x * int y; * 定义一个自动整型变量y,它的存储器 类型由编译模式确定 * 为了能够直接访

29、问这些特殊功能存放器,C51编译器扩充了关键字 sfr和 sfr16,利用这种扩充关键字可以在C语言源程序中直接对8051单片机的特殊功能存放器进行定义。定义方法如下: sfr 特殊功能存放器名 = 地址常数; 例如:sfr P0 = 0 x80;* 定义 IO口 P0,其地址为 80H * 这里需要注意的是,在关键字sfr后面必须是一个名字,名字可任意选取,但应符合一般习惯。等号后面必须是常数,不允许有带运算符的表达式,而且该常数必须在特殊功能存放器的地址范围之内80H0FFH。 在新一代的8051单片机中,特殊功能存放器经常组合成16位来使用。为了有效地访问这种16位的特殊功能存放器,可采

30、用关键字sfr16。 在8051单片机应用系统中经常需要访问特殊功能存放器中的某些位,C51编译器为此提供了一种扩充关键字sbit,利用它可以访问可位寻址对象。使用方法有如下三种: 1. sbit 位变量名 位地址; 这种方法将位的绝对地址赋给位变量,位地址必须位于80HOFFH之间。例如: sbit OV 0 xD2; 2. sbit 位变量名 特殊功能存放器名位位置; 当可寻址位位于特殊功能存放器中时可采用这种方法,“位位置是一个07之间的常数。例如sbit CY PSW7;3sbit 位变量名 字节地址位位置; 这种方法以一个常数字节地址作为基址,该常数必须在80HOFFH之间。“位位置

31、是一个07之间的常数。例如: sbit CY 0 xD07; 需要注意的是,sbit是一个独立的关键字,不要将它与关键字bit相混淆。 当位对象位于8051单片机内部存储器的可位寻址区时称之为“可位寻址对象。C51编译器提供了一个 bdata存储器类型,允许将具有 bdata类型的对象放入 8051单片机内部可位寻址区。例如: int bdata ibase * 在位寻址区定义一 个整型变量 ibase * char bdata array4; * 在位寻址区定义一个数组 array 4 * 使用关键字sbit可以独立访问可位寻址对象中的某一位。例如: sbit Ary37 = array37

32、; 采用这种方法定义可位寻址变量时要求基址对象的存储器类型为bdata,操作符“后面的位值的最大值取决于指定的基址类型,对于char来说是 07;对于int来说是 015;对于long来说是0 31。 用typedef重新定义数据类型,定义的方法如下: typedef 已有的数据类型 新的数据类型名 已有的数据类型是指C语言的所有数据类型,新的数据类型可按用户自己的习惯或根据任务需要决定。 7.2.4 运算符与表达式 运算符按其在表达式中所起的作用,可分为赋值运算符、算术运算符、增量与减量运算符、关系运算符、逻辑运算符、位运算符、复合赋值运算符、逗号运算符、条件运算符、指针和地址运算符、强制类

33、型转换运算符、sizeof运算符等。运算符按其在表达式中与运算对象的关系,又可分为单目运算符、双目运算符、三目运算符等。单目运算符需要一个运算对象,双目运算符要求二个运算对象,三目运算符要求三个运算对象。赋值运算符 赋值语句的格式: 变量 表达式; 符号“是赋值运算符,其作用是将一个数据的值赋给一个变量。利用赋值运算符将一个变量与一个表达式连接起来的式子称为赋值表达式,后面加“;构成赋值语句。2算术运算符 C语言中的算术运算符有: :加或取正值运算符,:减或取负值运算符; * :乘运算符,:除运算符,:取余运算符 用算术运算符将运算对象连接起来的式子称为算术表达式。算术表达式的一般形式为:表达

34、式1 算术运算符 表达式2 C语言中规定了运算符的优先级和结合性。在求一个表达式的值时,要按运算符的优先级别进行。算术运算符中取负值的优先级最高,其次是乘法*、除法和取余运算符,加法和减法运算符的优先级最低。需要时可在算术表达式中采用圆括号来改变运算符的优先级。 如果在一个表达式中各个运算符的优先级别相同,那么计算时按规定的结合方向进行。例如:由于+和-优先级别相同,计算时按“从左至右的结合方向,这种“从左至右的结合方向称为“左结合性,而“从右至左的结合方向称为“右结合性。3增量和减量运算符 C语言中除了根本的加、减、乘、除运算符之外,还提供一种特殊的运算符: :增量运算符 :减量运算符 增量

35、和减量是C语言中特有的一种运算符,它们的作用分别是对运算对象作加1和减l运算。例如:i,i, j,j等。 看起来i和 i的作用都是使变量 i的值加1,但是由于运算符所处的位置不同,使变量i加1的运算过程也不同。 i或i是先执行i1或i1操作,再使用i的值,而 i或i 是先使用i的值,再执行i 1或i1操作。 增量运算符和减量运算符只能用于变量,不能用于常数或表达式。 printf函数的一般形式: printf格式控制,输出参数表 格式控制又称为转换控制字符串,它是用双引号括起来的一些字符串,通常这些字符由格式说明、普通字符和转义字符三局部组成。 需要说明的是:允许作为库函数printf参量的总

36、字节数受C51编译器中函数库的限制。由于8051单片机存储器结构有限,在 SMALL和COMPACT 编译模式下,最多可传递15个字节的参数即5个指针,或1个指针和3个长字,在LARGE编译模式下,最多可传递40个字节的参数。 另外,在采用printf输出时,printf函数中输出参数表的每个输出参数的数据类型必须与程序中定义的变量类型一致,否那么会使输出的数据不对,这一点在使用库函数printf时是必须予以注意。4关系运算符 C语言中有6种关系运算符:大于、小于、=大于等于、=小于等于、 = =等于、 !=不等于。 前4种关系运算符具有相同的优先级,后两种关系运算符也具有相同的优先级;但前4

37、种的优先级高于后2种。用关系运算符将两个表达式连接起来即成为关系表达式。 关系表达式的一般形式为: 表达式1 关系运算符 表达式2 例如:x a、x + y b、x = 3 (y = 4) 都是合法的关系表达式。 关系运算符通常用来判别某个条件是否满足,关系运算的结果只有0和1两种值。当所指定的条件满足时结果为1,条件不满足时结果为0。 scanf函数的一般形式: scanf格式控制,指针参数表 其中指针参数是指指针变量或者用取地址运算符“&获取普通变量的地址。scanf函数中的每个参数都必须为指针,并且指针参数所指向的数据类型必须与格式控制串中所指定的格式相匹配,否那么scanf函数输入的数

38、据将不正确。5逻辑运算符 C语言中有3种逻辑运算符:逻辑或、逻辑与、 !逻辑非 逻辑运算符用来求某个条件式的逻辑值,用逻辑运算符将关系表达式或逻辑量连接起来就是逻辑表达式。逻辑表达式的一般形式为: 逻辑与:条件式 条件式 逻辑或:条件式 条件式 逻辑非:!条件式 当连接的两个条件式都为真时,逻辑与的结果为真1,否那么为假0。 当连接的两个条件式之中有一个为真时,逻辑或的结果为真1,否那么为假0。 当条件式的结果为真时,逻辑非的结果为假,反之,那么为真。 逻辑运算符的优先级为由高至低:!非,与,或。6位运算符 C语言有6种位运算符: 按位取反 按位与 左移 右移 按位异或 | 按位或 运算符的作

39、用是按位对变量进行运算,并不改变参与运算的变量的值。假设希望按位改变运算变量的值,那么应利用相应的赋值运算。另外位运算符不能用来对浮点型数据进行操作。 位运算符的优先级从高到低依次是: 按位取反、左移和右移、按位与、按位异或、按位或。 位运算符的一般形式如下: 变量1 位运算符 变量 2 按位取反、按位与、按位或、按位异或操作的运算取值关系如表7.3所示。表7.3 按位取反、按位与、按位或、按位异或操作运算取值关系xyxyx&yx|yxy00110000110011100101111001107复合赋值运算符 在赋值运算符“的前面加上其它运算符,就构成了所谓复合赋值运算符: + 加法赋值, 右

40、移位赋值,-减法赋值 逻辑与赋值 * 乘法赋值, 逻辑或赋值, 除法赋值 逻辑异或赋值 取模赋值, 逻辑非赋值, 左移位赋值。 复合赋值运算首先对变量进行某种运算,然后将运算的结果赋给该变量。复合运算的一般形式为: 变量 复合赋值运算符 表达式 采用这种复合赋值运算符,可以使程序简化,同时还可以提高程序的编译效率。8逗号运算符 在C语言中符号“,是一个特殊的运算符,可以用它将两个或多个表达式连接起来,称为逗号表达式。逗号表达式的一般形式为: 表达式1,表达式2, ,表达式n 程序运行时对于逗号表达式的处理,是从左至右依次计算出各个表达式的值,而整个逗号表达式的值是最右边表达式即表达式n的值。例

41、如:s = ( x = 4,y = 5,z = 6,10);执行这条命令的结果是x、y、z、s分别赋值4 、5 、6 、10。9条件运算符 条件运算将“?:是C语言中唯一的一个三目运算符,它要求有三个运算对象,用它可以将三个表达式连接构成一个条件表达式。条件表达式的一般形式如下: 逻辑表达式 ?表达式1 :表达式2 其功能是首先计算逻辑表达式,假设其值为真非 0值,将表达式 1的值作为整个条件表达式的值;当逻辑表达式的值为假0值时,将表达式2的值作为整个条件表达式的值。例如:max = ( a b ) ? a :b;执行这条命令的结果是把两个数a、b中的最大值赋给max。10指针和地址运算符

42、指针是C语言中一个十分重要的概念,在C语言的数据类型中专门有一种指针类型。变量的指针就是该变量的地址,可以定义一个指向某个变量的指针变量。为了表示指针变量和它所指向的变量地址之间的关系,C语言提供了两个专门的运算符: * 取内容, 取地址 取内容和取地址运算的一般形式分别为: 变量 * 指针变量 指针变量 目标变量 指针变量 目标变量 取内容运算的含义是将指针变量所指向的目标变量的值赋给左边的变量;取地址运算的含义是将目标变量的地址赋给左边的指针变量。需要注意的是,指针变量中只能存放地址即指针型数据,不要将一个非指针类型的数据赋值给一个指针变量。11强制类型转换运算符 C语言中的圆括号“也可作

43、为一种运算符使用,这就是强制类型转换运算符,它的作用是将表达式或变量的类型强制转换成为所指定的类型。C语言程序中进行算术运算时,需要注意数据类型的转换。有两种数据类型转换方式,即隐式转换和显式转换。隐式转换是在对程序进行编译时由编译器自动处理的。 在C语言中只有根本数据类型即char、int、long和float可以进行隐式转换。其余的数据类型不能进行隐式转换。强制类型转换运算符来进行显式转换。强制类型转换运算符的一般使用形式为: 类型 表达式 例如:需要在外部存储器xdata中定义一个字符型指针变量xp,并赋初值0 xC000,可以写成:xp = (char xdata * )0 xC000

44、;这种方法特别适合于用标识符来存取地址。12sizeof运算符 C语言中提供了一种用于求取数据类型、变量以及表达式的字节数的运算符: sizeof,该运算符的一般使用形式为: sizeof表达式或sizeof数据类型 应该注意的是,sizeof是一种特殊的运算符,不要错误地认为它是一个函数。实际上,字节数的计算在程序编译时就完成了,而不是在程序执行的过程中才计算出来的。例如:int a = sizeof(float); 执行这条命令的结果是把4赋给了整型变量a,这意味着一个单精度数存储时占有4个字节内存。7.3C51 程序设计 7.3.1表达式语句 C语言是一种结构化的程序设计语言,它提供了十

45、分丰富的程序控制语句。表达式语句是最根本的一种语句。在表达式的后边加一个分号“;就构成了表达式语句。 表达式语句也可以仅由一个分号“;组成,这种语句称为空语句。空语句是表达式语句的一个特例。空语句在程序设计中有时是很有用的,当程序在语法上需要有一个语句,但在语义上并不要求有具体的动作时,便可以采用空语句。空语句通常有两种用法: 1在程序中为有关语句提供标号,用以标记程序执行的位置。 2在用while语句构成的循环语句后面加一个分号,形成一个不执行其它操作的空循环体。 7.3.2复合语句 复合语句是由假设干条语句组合而成的一种语句,它是用一个大括号“将假设干条语句组合在一起而形成的一种功能块。复

46、合语句不需要以分号“;结束,但它内部的各条单语句仍需以分号“;结束。复合语句的一般形式为: 局部变量定义; 语句1; 语句2; 。 语句n; 复合语句在执行时,其中的各条单语句依次顺序执行。整个复合语句在语法上等价于一条单语句,因此在C语言程序中可以将复合语句视为一条单语句。复合语句允许嵌套,即在复合语句内部还可以包含别的复合语句。 通常复合语句都出现在函数中,实际上,函数的执行局部即函数体就是一个复合语句。复合语句中的单语句一般是可执行语句,此外还可以是变量的定义语句说明变量的数据类型。用复合语句内部变量定义语句所定义的变量,称为该复合语句中的局部变量,它仅在当前这个复合语句中有效。利用复合

47、语句将多条单语句组合在一起,以及在复合语句中进行局部变量定义是C语言的一个重要特征。7.3.3流程控制语句 选择结构 if语句 if语句有三种形式:单分支选择if语句、双分支选择if语句和多分支选择if语句。 1单分支选择语句 If ( 条件表达式 ) 语句 其含义为:假设条件表达式的结果为真非0值,就执行了后面的语句;反之,假设条件达式的结果为假0值,就不执行后面的语句。这里的语句也可以是复合语句。这种条件语句的执行过程如图7.3a所示。 2双分支选择语句 if条件表达式 语句 1; else 语句2; 其含义为:假设条件表达式的结果为真非0值,就执行语句1;反之,假设条件表达式的结果为假0

48、值,就执行语句2。这里的语句1和语句2均可以是复合语句。这种条件语句的执过程如图7.3b所示。 (a) (b) 图7.3条件语句的执行 3 多分支选择语句 if条件表达式1 语句 1; else if条件式表达2 语句 2; else if条件式表达3 语句 3; else if条件表达式 n 语句 n else 语句n+1; 这种条件语句常用来实现多方向条件分支,其执行过程如图7.4所示。 例3.1 利用条件语句求一元二次方程的根 #include #include main( ) float a,b,c,x1,x2; float r,s; a = 2.0;b = 3.0;c = 4.0;r

49、 = b*b4.0*a*c; if ( r 0.0 ) s = sqrt (r); x1 = (bs)(2.0*a); x2 = (bs)(2.0*a); printf(“real:x1 = %15.7f,x2 = %15.7fn,x1,x2); else if (r = = 0.0) printf(“double:x1,x2 = %15.7n,b(2.0*a); else x1 = b(2.0*a); x2 = sqrt(r)(2.0*a); printf(“complex:re = %15.7f,im = %15.7fn,x1,x2); 程序执行结果:complex:re 0.750000

50、0,im 1.1989580 这种条件语句常用来实现多方向条件分支,其执行过程如图7.4所示。 switch语句 开关语句也是一种用来实现多方向条件分支的语句。开关语句可直接处理多分支选择,使程序结构清晰,使用方便。开关语句是用关键字switch构成的,它的一般形式如下: switch表达式 case 常量表达式1 : 语句 1; break; case 常量表达式2 : 语句2; break; case 常量表达式n : 语句n; break; default: 语句n+1; 图7.5 开关语句的执行过程循环结构 在C语言程序中用来构成循环控制的语句有:while语句、dowhile语句、f

51、or语句以及goto语句,分述如下: while语句 采用while语句构成循环结构的一般形式如下: while (条件表达式) 语句; 其意义为,当条件表达式的结果为真非0值时,程序就重复执行后面的语句,一直执行到条件表达式的结果变化为假0值时为止。这种循环结构是先检查条件表达式所给出的条件,再根据检查的结果断定是否执行后面的语句。如果条件表达式的结果一开始就为假,那么后面的语句一次也不会被执行。这里的语句可以是复合语句。图7.6所示为while语句的执行过程。 dowhile语句 采用do一while语句构成循环结构的一般形式如下: do 语句 while条件表达式; 这种循环结构的特点是

52、先执行给定的循环体语句,然后再检查条件表达式的结果。当多件表达式的值为真非0值时,那么重复执行循环体语句,直到条件表达式的值变为假0值时为止。因此,用如do一while语句构成的循环结构在任何条件下,循环体语句至少会被执行一次。图7.7绘出了这种循环结构的流程图。 图7.6 while语句的执行过程 图7.7 dowhile循环结构的流 例:3.2 while语句计算1-100的累加和 #include main( ) int i = 1,s = 0; while (i = 100) s = s+i;i+; printf (“s = %d/n,s); 例3.3 do-while语句计算1-10

53、0的累加和 #include main( ) int i = 1,s = 0; do s = s+i;i+; while ( i = 100) printf (“s = %d/n,s); for语句 采用for语句构成循环结构的一般形式如下: for初值设定表达式;循环条件表达式;更新表达式语句 for语句的执行过程是:先计算出初值设定表达式的值作为循环控制变量的初值,再检查循环条件表达式的结果,当满足循环条件时就执行循环体语句并计算更新表达式,然后再根据更新表达式的计算结果来判断循环条件是否满足一直进行到循环条件表达式的结果为假 0值时,退出循环体。for语句的执行过程如图 7.8所示。 在

54、C语言程序的循环结构中,for语句的使用最为灵活,它不仅可以用于循环次数已经确定的情况,而且可以用于循环次数不确定而只给出循环结束条件的情况。另外,for语句中的三个表达式是相互独立的,并不一定要求三个表达式之间有依赖关系。并且 for语句中的三个表达式都可能缺省,但无论缺省哪一个表达式,其中的两个分号都不能缺省。一般不要缺省循环条件表达式,以免形成死循环。例3. 用for 语句计算自然数1 100的累积和 #include main( ) int i = 1,s = 0; for( ;i = 100;) s = s+i; i+; printf (“s = %d n,s); 图7.8 for语

55、句的执行过程非结构化语句 goto语句 goto语句是一个无条件转向语句,它的一般形式为: goto 语句标号; 其中语句标号是一个带冒号“:的标识符。将goto语句和if语句一起使用,可以构成一个循环结构。但更常见的是在C语言程序中采用goto语句来跳出多重循环,需要注意的是只能用goto语句从内层循环跳到外层循环,而不允许从外层循环跳到内层循环。 对于多重循环的情况,break语句只能跳出它所处的那一层循环,而不象goto语句可以直接从最内层循环中跳出来。由此可见,要退出多重循环时,采用goto语句比较方便。需要指出的是,break语句只能用于开关语句和循环语句之中,它是一种具有特殊功能的

56、无条件转移语句。另外还要注意,在进行实际程序设计时,为了保证程序具有良好的结构,应当尽可能地少采用goto语句,以使程序结构清晰易读。 continue语句 continue语句是一种中断语句,它一般用在循环结构中,其功能是结束本次循环,即跳过循环体中下面尚未执行的语句,把程序流程转移到当前循环语句的下一个循环周期,并根据循环控制条件决定是否重复执行该循环体。 continue语句的一般形式为:continue; continue语句通常和条件语句一起用在由 while、dowhile和 for语句构成的循环结构中,它也是一种具有特殊功能的无条件转移语句,但它与 break语句不同,conti

57、nue语句并不跳出循环体,而只是根据循环控制条件确定是否继续执行循环语句 返回语句 返回语句用于终止函数的执行,并控制程序返回到调用该函数时所处的位置。返回语句有两种形式: lreturn表达式; 2return; 如果return语句后边带有表达式,那么要计算表达式的值,并将表达式的值作为该函数的返回值。假设使用不带表达式的第2种形式,那么被调用函数返回主调用函数时,函数值不确定。一个函数的内部可以含有多个return语句,但程序仅执行其中的一个return语句而返回主调用函数。一个函数的内部也可以没有return语句,在这种情况下,当程序执行到最后一个界限符“处时,就自动返回主调用函数。

58、7.4 函数 函数是C语言中的一种根本模块,实际上一个C语言程序就是由假设干个模块化的函数所构成的。前面我们已经看到,C语言程序总是由主函数 main开始,main函数是一个控制程序流程的特殊函数,它是程序的起点。在进行程序设计的过程中,如果所设计的程序较大,一般应将其分成假设干个子程序模块,每个子程序模块完成一种特定的功能。在C语言中,子程序是用函数来实现的。对于一些需要经常使用的子程序可以按函数来设计,并且可以将自己所设计的功能函数做成一个专门的函数库,以供反复调用。此外,C51编译器还提供了丰富的运行库函数,用户可以根据需要随时调用。这种模块化的程序设计方法,可以大大提高编程效率。7.4

59、.1 函数的定义 从用户的角度来看,有两种函数:标准库函数和用户自定义函数。标准库函数是C51编译器提供的,不需要用户进行定义,可以直接调用。用户自定义函数是用户根据自己的需要编写的能实现特定功能的函数,它必须先进行定义之后才能调用。 函数定义的一般形式为: 函数类型 函数名形式参数表 形式参数说明; 局部变量定义; 函数体语句; 其中,“函数类型说明了自定义函数返回值的类型。 “函数名是自定义函数的名字。 “形式参数表中列出的是在主调用函数与被调用函数之间传递数据的形式参数,形式参数的类型必须要加以说明。ANSI C标准允许在形式参数表中对形式参数的类型进行说明。如果定义的是无参函数,可以没

60、有形式参数表,但圆括号不能省略。 “局部变量定义是对在函数内部使用的局部变量进行定义。 “函数体语句是为完成该函数的特定功能而设置的各种语句。 如果定义函数时只给出一对花括号而不给出其局部变量和函数体语句,那么该函数为所谓“空函数,这种空函数也是合法的。在进行C语言模块化程序设计时,各模块的功能可通过函数来实现。开始时只设计最根本的模块,其它作为扩充功能在以后需要时再加上。编写程序时可在将来准备扩充的地方写上一个空函数,这样可使程序的结构清晰,可读性好,而且易于扩充。7.4.2 函数的调用形式 1调用形式 C语言程序中函数是可以互相调用的。所谓函数调用就是在一个函数体中引用另外一个已经定义了的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论