资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第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,语言编写的程序能够很容易地在不同类型的计算机之间进行移植。与其它计算机高级语言相比,,C,语言具有它自身的特点:,1语言简洁,使用方便灵活。,2可移植性好。,3表达能力强。,4可进行结构化程序设计。,5可以直接操作计算机硬件。,6生成的目标代码质量高。,尽管,C,语言具有很多的优点,但和其它任何一种程序设计语言一样,也有其自身的缺点,如,不能自动检查数组的边界,,,各种运算符的优先级别太多,,某些运算符具有多种用途等。,C,语言程序是由若干个函数单元组成的,每个函数都是完成某个特殊任务的子程序段。组成一个程序的若干个函数可以保存在一个源程序文件中,也可以保存语言源程序文件的文件名由程序设计人员根据某种俗成规则自己确定,其扩展名统一为“.,C”。,如,A1-1.C、A2-1.C。,C,语言程序的,开始部分通常是预处理命令,,如程序中通常遇到的,include,命令。这个预处理命令通知编译器在对程序进行编译时,将所需要的头文件读入后再一起进行编译。一般在“头文件”中包含有程序在编译时的一些必要的信息,通常,C,语言编译器都会提供若干个不同用途的头文件。,头文件的读入是在对程序进行编译时才完成的,。,名门棋牌官网,1PK1棋牌公社官网,编辑整理,C,语言程序是由函数所组成的。一个完整的,C,语言程序应包含一个,主函数,main(),和若干个其它功能的函数。函数之间,可以相互调用,,但,main(),函数只能调用其它的功能函数,,而不能被其它函数所调用。功能函数可以是,C,语言编译器提供的库函数,也可以由用户按实际需要自行编写的函数。不管,main(),函数处于程序中的什么位置,,程序总是从,main(),函数开始执行,。一个函数必须预先定义或声明后才能调用。,函数定义或声明位于源程序的预处理命令之后的开始位置。,函数定义部分包括有函数的存储类型、返回值数据类型、函数名、形式参数说明等,,函数名后面必须跟一个圆括弧(),形式参数说明在圆括弧()内进行。函数也可以没有形式参数,如,main()。,函数的位置比较自由。可以由程序设计人员安排在函数定义后的任意位置。函数由函数名和一对花括弧“”组成,在“”里面的内容就是函数体,如果一个函数有多个“”,则最外面的一对“”为函数体的范围。,函数体的内容为若干条语句,一般有两类语句,一类为说明语句,用来对函数中将要用到的变量进行定义;另一类为执行语句,用来完成一定的功能或算法处理。有的函数体仅有一对“”,其中既没有变量定义语句,也没有执行语句,这也是合法的,称为“空函数”。,C,语言源程序可以采用任何一种编辑器来编写,既可以是,windows,环境下的编辑器,如记事本(,NOTEPAD),或写字板(,WORDPAD),,也可以是,DOS,环境下的编辑器,如,EDIT,或,PE,等。,C,语言程序的书写格式十分自由。,一条语句可以写成一行,也可以写成几行;还可以在一行内写多条语句;但是需要注意的是,每条语句都必须以分号“;”作为结束符,。,另外,,C,语言区分大小写字母,,,C,语言编译器在对程序进行编译时,对于程序中同一个字母的大小写作为不同的变量来处理。虽然,C,语言程序不要求具有固定的格式,但我们在实际编写程序时还是应该遵守一定的规则,一般应按程序的功能以“缩格”形式来写程序,同时还应在适当的地方加上,必要的注释,。注释对于比较大的程序来说是十分重要的,这有利于修改与读懂程序。,C,语言本身没有输入输出功能,,C,语言程序的输入和输出是通过函数调用来实现的。,Franklin C51,编译器提供的输入输出库函数,scanf,和,printf,是通过 8051单片机的串行口实现的,,在程序中使用这种输入输出库函数之前必须先对8051单片机的串行口进行初始化。但是对于单片机应用系统来说,由于具体要求的不同,应用系统的输入输出方式多种多样,不可能一律采用串行口作输入和输出。因此应该根据实际需要,由,应用系统的研制人员自己来编写满足特定需要的输入输出函数,,这一点对于单片机应用系统的开发研制人员来说是十分重要的。,7.1.2,C,语言的标识符和关键字,C,语言的标识符是用来标识源程序中某个对象名字的。这些对象可以是函数、变量、常量、数组、数据类型、存储方式、语句等。一个标识符由字符串、数字和下划线等组成,,第一个字符必须是字母或下划线,,,通常以下划线开头的标识符是编译系统专用的,,因此在编写,C,语言源程序时,一般不要使用以下划线开头的标识符,而将下划线用作分段符,。,C51,编译器规定标识符,最长可达255个字符,,但只有前面32个字符在编译时有效,因此在编写源程序时标识符的长度不要超过 32个字符。程序中对于标识符的命名应当简洁明了,含义清晰,便于阅读理解,如用标识符“,max”,表示最大值,用“,TIMER0”,表示定时器0等。,关键字是一类具有固定名称和特定含义的特殊标识符,又称为,保留字,。在编写,C,语言源程序时一般不允许将关键字另作别用,换句话说就是,对于标识符的命名不要与关键字相同,。在,C,语言中,,ANSI C,标准一共规定了32个关键字,表 7.1按用途列出了,ANSI C,标准的关键字。,表 7,.,1,ANSI C,标准的关键字,关键字,用 途,说 明,auto,break,case,char,const,continue,default,do,double,else,enum,extern,float,for,goto,if,int,long,register,return,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile,while,存储类说明,程序语句,程序语句,数据类型说明,存储类型说明,程序语句,程序语句,程序语句,数据类型说明,程序语句,数据类型说明,存储种类说明,数据类型说明,程序语句,程序语句,程序语句,数据类型说明,数据类型说明,存储种类说明,程序语句,数据类型说明,数据类型说明,运算符,存储种类说明,数据类型说明,程序语句,数据类型说明,数据类型说明,数据类型说明,数据类型说明,数据类型说明,程序语句,用以说明局部变量,退出最内层循环,switch,语句中的选择项,单字节整型数或字符型数据,在程序执行过程中不可能修改的变量值,转向下一个循环,switch,语句中的失败选择项,构成,dowhile,循环结构,双精度浮点数,构成,ifelse,选择结构,枚举,在其它程序模块中说明了的全局变量,单精度浮点数,构成,for,循环结构,构成,goto,转移结构,构成,ifelse,选择结构,基本整型数,长整型数,使用,CPU,内部寄存器的变量,函数返回,短整型数,有符号数,二进制数据的最高位为符号位,计算表达式或数据类型的字节数,静态变量,结构类型数据,构成,switch,选择结构,重新进行数据类型定义,联合数据类型,无符号数据,无符号数据,说明该变量在程序执行中可被隐含地改变,构成,while,和,dowhile,循环结构,关键字,用 途,说 明,bit,sbit,sfr,sfr16,data,bdata,idata,pdata,xdata,code,interrupt,Using,reetrant,位标量声明,位标量声明,特殊功能寄存器声明,特殊功能寄存器声明,存储器类型声明,存储器类型声明,存储器类型说明,存储器类型说明,存储器类型说明,存储器类型说明,中断函数说明,寄存器组定义,再入函数声明,声明一个位标量或位类型的函数,声明一个可位寻址变量,声明一个特殊功能寄存器(8位),声明一个16位的特殊功能寄存器,直接寻址,的8051内部数据存储器,可位寻址,的8051内部数据存储器,间接寻址,的8051内部数据存储器,“,分页,”寻址的8051外部数据存储器,8051,外部,数据存储器,8051程序存储器,定义一个中断函数,定义8051工作寄存器组,定义一个再入函数,C51,编译器除了支持,ANSI C,标准关键字以外,还扩展了如表7.2所示的关键字:,表7.2,C51,编译器的扩展关键字,7.1.3 单片机,C51,程序的编译连接与调试,Franklin C51,交叉编译器是专为8051系列单片机设计的,C,语言编译器,它能在,IBM PC,及其兼容机上运行,使用非常方便。为了保证编译器能正常工作,,PC,机应具有512,K,以上的内存、一个软盘驱动器、一个硬盘,采用,MSDOS 3.0,以上版本的操作系统。,Franklin C51,以软件包的形式提供,软件包中主要有,C51,交叉编译器、,A51,交叉汇编器、,L51,连接定位器、,OHS51,代码转换器和,dScope,一51软件仿真调试器以及其它一些实用软件程序。如果在,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,编译器可根据不同的硬件环境由4个文件做出修改。下列配置文件包括在,C51,软件包中:,STARTUP.A51:C51,编译器的启动程序,所有的栈指针和存贮器,只要需要,将被初始化。,INT.A51:,在文件中已明确初始化了的变量作初始化。如果系统装了“看门狗”,该文件可包含附加的“看门狗”刷新。,PUTCHAR.C:,函数“,printf,”、“puts”,等的字符输出核心程序,该程序可根据用户硬件加以修改(如,LCD,显示)。,GETKEY.C:,函数“,getchar,”、“,scanf,”,等的字符输入核心程序,该程序可根据硬件加以修改(如矩阵键盘),所有文件都包含在,C,运行库中,因此,不能在连接时指定调用。如果用户改变一个文件,可将其编译后与其它目标文件一起连接,因而不必改动运行库。库中原文件自动忽略。,例:,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,是编译控制指令。输入完命令后回车,即可进人编译过程。如果编译过程中未发现错误,屏幕上会显示出:,C51 COMPILATION COMPILETE,0 WARING(S),0 ERROR(S),并产生列表文件,EXI2.LST,和目标文件,EXI2.OBJ。,如果编译中发现任何错误,则不产生目标文件,而将所有的错误信息都在列表文件中表示出来。,编译控制指令,CODE,使列表文件的后面附加一个汇编语言文件,。编译控制指令,DEBUG,使目标文件中包含有进行源程序调试时需要的各种符号信息。目标文件中还包含有可再定位的目标码,以供,L51,连接器作进一步的处理。,C51,编译器提供了许多不同控制指令可以完成各种编译控制功能。,7.2,C51,程序设计的基本语法,C,语言是一种程序设计语言,采用,C,语言进行程序设计时,需要遵循一定的语法规则。,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”,表示负数。,负数用补码表示,。所能表示的数值范围是,-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。,它们的长度均为四个字节。,singed long,是有符号的长整型数据,字节中的最高位表示数据的符号,“0”表示正数,“1”表示负数。数值的表示范围是,2147483648 2147483647,;,unsigned long,是无符号长整型数据,数值的表示范围是,04294967295,。,4,float,浮点型。它是符合,IEEE754,标准的单精度浮点型数据,在十进制中具有7位有效数字。,float,型数据占用四个字节(2位二进制数)。需要指出的是,对于浮点型数据除了有正常数值之外,还可能出现非正常数值。根据,IEEE,标准,当浮点型数据取以下数值(16进制数)时即为非正常值:,FFFFFFFFH,非数(,NaN,);7F800000H,正溢出(,INF);FF800000H,负溢出(,INF);,另外,由于,8051单片机不包括捕获浮点运算错误的中断向量,,因此必须由用户自己根据可能出现的错误条件用软件来进行适当的处理。,5*指针型。指针型数据不同于以上四种基本数据类型,,它本身是一个变量,但在这个变量中存放的不是普通的数据而是指向另一个数据的地址,。指针变量也要占据一定的内存单元,在,C51,中指针变量的长度一般为3个字节。指针变量也具有类型,其表示方法是在指针符号“*”的前面冠以数据类型符号。如,char *,Pointl,;,表示,Pointl,是一个字符型的指针变量。指针变量的类型表示该指针所指向地址中数据的类型。使用指针型变量可以方便地,对8051单片机的各部分物理地址直接进行操作,。,6,bit,位标量,。这是,C 51,编译器的一种扩充数据类型,利用它可定义一个位标量,但,不能定义位指针,也不能定义位数组,。,7,sfr,特殊功能寄存器,。这也是,C 51,编译器的一种扩充数据类型,利用它,可以访问8051单片机的所有内部特殊功能寄存器,。,sfr,型数据占用一个内存单元,其取值范围0255。,8,sfr16 16,位特殊功能寄存器,。它占用两个内存单元,取值范围是065535。,9,sbit,可寻址,位。这也是,C51,编译器的一种扩充数据类型,利用它,可以访8051单片机内部,RAM,中的可寻址位或特殊功能寄存器中的可寻址位,。,在,C,语言程序中的表达式或变量赋值运算中,有时会出现,运算对象的数据不一致,的情况,,C,语言允许任何标准数据类型之间的,隐式转换,。隐式转换按以下优先级别自动进行:,bit char,int,long float signed unsigned,转换时由低向高进行,而不是数据转换时的顺序。一般来说,如果有几个不同类型的数据同时参加运算,先将低级别类型的数据转换成高级别类型,再作运算处理,并且运算结果为高级别类型数据。,C51,编译器除了能支持以上这些基本数据之外,还能支持一些复杂的构造型数据,如结构类型、联合类型等。,7.2.2 常量,常量是在程序执行过程中其值不能改变的量。常量的数据类型有整型、浮点型、字符型和字符串型等,,C51,编译器还扩充了一种位(,bit),标量。分别说明如下:,1整型常量,整型常量就是整型常数,可表示为以下几种形式:十进制整数;十六进制整数:以 0,X,开头的数是十六进制数,,ANSI C,标准规定十六进制数的数字为09,再加字母,af;,长整数:在数字后面加一个字母,L,就构成了长整数。,2浮点型常量,浮点型常量有十进制表示形式和指数表示形式。,十进制表示形式又称定点表示形式,由数字和小数点组成。如 0.3141、31.41、314.1及0.0都是十进制数表示形式的浮点型常量。,在这种表示形式中,如果整数或小数部分为0可以省略不写,但必须有小数点。,指数表示形式为:,数字数字,e,数字,其中,中的内容为可选项,可有可无,但其余部分必须有。,3字符型常量,字符型常量是单引号内的字符,如,a、b,等。对于,不可显示的控制字符,可以在该字符前面加一个反斜杠字符“”组成专用转义字符,。利用转义字符可以完成一些特殊功能和输出时的格式控制。,4字符串型常量,字符串型常量由,双引号“”内的字符组成,。当双引号内的字符个数为0时,称为空串常量。需要注意的是,字符串常量首尾的双引号是界限符,当需要表示双引号字符串时,可用转义字符来表示为:“”。,如:“,I say:“goodbye!”,字符串为,I say:“goodbye!”,另外,,C,语言将字符串常量作为一个字符类型数组来处理,在存储字符串常量时,要在字符串的尾部加一个转义字符0作为该字符串常量的结束符。因此不要将字符常量与字符串常量混淆。,5位标量,这是,C51,编译器的一种扩充数据类型。位标量用关键字“,bit”,来定义,它的值是一个二进制位。一个函数中可以包含“,bit”,类型的参数,函数的返回值也可为“,bit”,型。另外,,不能定义位指针,也不能定义位数组,。,7.2.3 变量及其存储模式,和常量相比,变量是另一种量,在程序执行过程中其值能不断变化。每一个变量都必须有一个标识符作为它的变量名。在使用一个变量之前,必须先对该变量进行定义,指出它的数据类型和存储模式,以便编译系统为它分配相应的存储单元。在,C51,中对变量进行定义的格式如下:,存储种类数据类型存储器类型变量名表;,其中,“存储种类”和“存储器类型”是可选项。变量的存储种类有四种:,自动(,auto)、,外部(,extern)、,静态(,static),和寄存器(,register),。,在定义一个变量时如果省略存储种类选项,则该变量将为自动(,auto),变量。,定义一个变量时除了需要说明其数据类型之外,,C51,编译器还允许说明变量的存储器类型。,Franklin C51,对于每个变量可以准确地赋予其存储器类型,从而可使之能够在单片机系统内准确地定位。,定义变量时如果省略“存储器类型”选项,则按编译模式,SMALL、COMPACT,或,LARGE,所规定的默认存储器类型确定变量的存储区域,不能位于寄存器中的参数传递变量和过程变量也保存在默认的存储器区域。,C51,编译器的三种存储器模式(默认的存储器类型)对变量的影响如下:,1.,SMALL,变量被定义在 8051单片机的内部数据存储器中,,因此对这种变量的访问速度最快。另外,所有的对象,包括堆栈,都必须嵌入内部数据存储器,而堆栈的长度是很重要的,实际栈长取决于不同函数的嵌套深度。,2.,COMPACT,变量被定义在分页外部数据存储器,中,外部数据段的长度可达256字节。这时对变量的访问是通过寄存器间接寻址(,MOVX,Ri,),进行的,堆栈位于8051单片机内部数据存储器中。采用这种编译模式时,变量的高 8位地址由,P2,口确定。因此,在采用这种模式的同时,必须适当改变启动程序,STARTUPA51,中的参数:,PDATASTART,和,PDATALEN;,用,L51,进行连接时还必须采用连接控制命令,PDATA,来对,P2,口地址进行定位,这样才能确保,P2,口为所需要的高8位地址。,3.,LARGE,变量被定义在外部数据存储器中,(最大可达64,K,字节),使用数据指针,DPTR,来间接访问变量。,这种访问数据的方法效率是不高的,,尤其是对于2个或多个字节的变量,用这种数据访问方法相当影响程序的代码长度。另外一个不方便之处是这种数据指针不能对称操作。,需要特别指出的是,变量的存储种类与存储器类型是完全无关的。例如:,static unsigned char data x;*,在内部数据,存储器中定义一个静态无符号字符型变量,x *,int,y;*,定义一个自动整型变量,y,,它的存储器,类型由编译模式确定 *,为了能够直接访问这些特殊功能寄存器,,C51,编译器扩充了关键字,sfr,和,sfr16,,利用这种扩充关键字可以在,C,语言源程序中直接对8051单片机的特殊功能寄存器进行定义。定义方法如下:,sfr,特殊功能寄存器名=地址常数;,例如:,sfr,P0=0 x80;*,定义,IO,口,P0,,其地址为 80,H*,这里需要注意的是,在关键字,sfr,后面必须是一个名字,名字可任意选取,但应符合一般习惯。等号后面必须是常数,不允许有带运算符的表达式,而且该常数必须在特殊功能寄存器的地址范围之内(80,H0FFH)。,在新一代的8051单片机中,特殊功能寄存器经常组合成16位来使用。为了有效地访问这种16位的特殊功能寄存器,可采用关键字,sfr16。,在8051单片机应用系统中经常需要访问特殊功能寄存器中的某些位,,C51,编译器为此提供了一种扩充关键字,sbit,,,利用它可以访问可位寻址对象。使用方法有如下三种:,1.,sbit,位变量名 位地址;,这种方法将位的绝对地址赋给位变量,位地址必须位于80,HOFFH,之间。例如:,sbit,OV 0 xD2;,2.,sbit,位变量名 特殊功能寄存器名位位置;,当可寻址位位于特殊功能寄存器中时可采用这种方法,“位位置”是一个07之间的常数。例如,sbit,CY PSW7;,3,sbit,位变量名 字节地址位位置;,这种方法以一个常数(字节地址)作为基址,该常数必须在80,HOFFH,之间。“位位置”是一个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;,采用这种方法定义可位寻址变量时要求基址对象的存储器类型为,bdata,,,操作符“”后面的位值的最大值取决于指定的基址类型,对于,char,来说是 07;对于,int,来说是 015;对于,long,来说是0 31。,用,typedef,重新定义数据类型,定义的方法如下:,typedef,已有的数据类型 新的数据类型名,已有的数据类型是指,C,语言的所有数据类型,新的数据类型可按用户自己的习惯或根据任务需要决定。,7.2.4 运算符与表达式,运算符按其在表达式中所起的作用,可分为赋值运算符、算术运算符、增量与减量运算符、关系运算符、逻辑运算符、位运算符、复合赋值运算符、逗号运算符、条件运算符、指针和地址运算符、强制类型转换运算符、,sizeof,运算符等。运算符按其在表达式中与运算对象的关系,又可分为单目运算符、双目运算符、三目运算符等。单目运算符需要一个运算对象,双目运算符要求二个运算对象,三目运算符要求三个运算对象。,赋值运算符,赋值语句的格式:,变量 表达式;,符号“”是,赋值运算符,,其作用是将一个数据的值赋给一个变量。利用赋值运算符将一个变量与一个表达式连接起来的式子称为赋值表达式,后面加“;”构成赋值语句。,2算术运算符,C,语言中的算术运算符有:,:加或取正值运算符,:减或取负值运算符;,*,:乘运算符,:除运算符,:取余运算符,用算术运算符将运算对象连接起来的式子称为算术表达式。,算术表达式的一般形式为:表达式1 算术运算符 表达式2,C,语言中规定了运算符的优先级和结合性。在求一个表达式的值时,要,按运算符的优先级别进行,。算术运算符中取负值()的优先级最高,其次是乘法(*)、除法()和取余()运算符,加法()和减法()运算符的优先级最低。需要时可,在算术表达式中采用圆括号来改变运算符的优先级,。如果在一个表达式中各个运算符的优先级别相同,则计算时按规定的结合方向进行。例如:由于+和-优先级别相同,计算时按“从左至右”的结合方向,这种“从左至右”的结合方向称为“左结合性”,而“从右至左”的结合方向称为“右结合性”。,3增量和减量运算符,C,语言中除了基本的加、减、乘、除运算符之外,还提供一种特殊的运算符:,:增量运算符 :减量运算符,增量和减量是,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,参量的总字节数受,C51,编译器中函数库的限制。,由于8051单片机存储器结构有限,在,SMALL,和,COMPACT,编译模式下,最多可传递15个字节的参数,(即5个指针,或1个指针和3个长字),,在,LARGE,编译模式下,最多可传递40个字节的参数,。,另外,在采用,printf,输出时,,printf,函数中输出参数表的每个输出参数的数据类型必须与程序中定义的变量类型一致,否则会使输出的数据不对,这一点在使用库函数,printf,时是必须予以注意。,4关系运算符,C,语言中有6种关系运算符:(大于)、(小于)、=(大于等于)、=(小于等于)、=(等于)、!=(不等于)。,前4种关系运算符具有相同的优先级,后两种关系运算符也具有相同的优先级;但前4种的优先级高于后2种。用关系运算符将两个表达式连接起来即成为关系表达式。,关系表达式的一般形式为:,表达式1 关系运算符 表达式2,例如:,x a、x+y b、(x=3)(y=4),都是合法的关系表达式。,关系运算符通常用来判别某个条件是否满足,,关系运算的结果只有0和1两种值,。当所指定的,条件满足时结果为1,条件不满足时结果为0,。,scanf,函数的一般形式:,scanf,(,格式控制,指针参数表),其中指针参数是指指针变量或者用取地址运算符“&”获取普通变量的地址。,scanf,函数中的每个参数都必须为指针,并且指针参数所指向的数据类型必须与格式控制串中所指定的格式相匹配,否则,scanf,函数输入的数据将不正确。,5逻辑运算符,C,语言中有3种逻辑运算符:(逻辑或)、(逻辑与)、!(逻辑非),逻辑运算符用来求某个条件式的逻辑值,用逻辑运算符将关系表达式或逻辑量连接起来就是逻辑表达式。逻辑表达式的一般形式为:,逻辑与:条件式 条件式,逻辑或:条件式 条件式,逻辑非:!条件式,当连接的两个条件式都为真时,逻辑与的结果为真(1),否则为假(0)。,当连接的两个条件式之中有一个为真时,逻辑或的结果为真(1),否则为假(0)。,当条件式的结果为真时,逻辑非的结果为假,反之,则为真。,逻辑运算符的优先级为(由高至低):!(非),(与),(或)。,6位运算符,C,语言有6种位运算符:,(按位取反)(按位与),(左移)(右移),(按位异或)|(按位或),运算符的作用是按位对变量进行运算,并不改变参与运算的变量的值。若希望按位改变运算变量的值,则应利用相应的赋值运算。另外位运算符不能用来对浮点型数据进行操作。,位运算符的优先级从高到低依次是:,按位取反()、左移()和右移()、按位与()、按位异或()、按位或()。,位运算符的一般形式如下:,变量1 位运算符 变量 2,按位取反()、按位与()、按位或()、按位异或()操作的运算取值关系如表7.3所示。,表7.3 按位取反、按位与、按位或、按位异或操作运算取值关系,x,y,x,y,x&y,x|y,xy,0,0,1,1,0,0,0,0,1,1,0,0,1,1,1,0,0,1,0,1,1,1,1,0,0,1,1,0,7复合赋值运算符,在赋值运算符“”的前面加上其它运算符,就构成了所谓复合赋值运算符:,+加法赋值,右移位赋值,-减法赋值 逻辑与赋值,*乘法赋值,逻辑或赋值,除法赋值 逻辑异或赋值,取模赋值,逻辑非赋值,左移位赋值。,复合赋值运算首先对变量进行某种运算,然后将运算的结果赋给该变量。复合运算的一般形式为:,变量 复合赋值运算符 表达式,采用这种复合赋值运算符,可以使程序简化,同时还可以提高程序的编译效率。,8逗号运算符,在,C,语言中符号“,”是一个特殊的运算符,可以用它将两个(或多个)表达式连接起来,称为逗号表达式。逗号表达式的一般形式为:,表达式1,表达式2,表达式,n,程序运行时对于逗号表达式的处理,是从左至右依次计算出各个表达式的值,而整个逗号表达式的值是最右边表达式(即表达式,n),的值。例如:,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,指针和地址运算符,指针是,C,语言中一个十分重要的概念,在,C,语言的数据类型中专门有一种指针类型。变量的指针就是该变量的地址,可以定义一个指向某个变量的指针变量。为了表示指针变量和它所指向的变量地址之间的关系,,C,语言提供了两个专门的运算符:,*取内容,取地址,取内容和取地址运算的一般形式分别为:,变量 *指针变量,指针变量 目标变量,指针变量 目标变量,取内容运算的含义是将指针变量所指向的目标变量的值赋给左边的变量;取地址运算的含义是将目标变量的地址赋给左边的指针变量。需要注意的是,指针变量中只能存放地址(即指针型数据),不要将一个非指针类型的数据赋值给一个指针变量。,11强制类型转换运算符,C,语言中的圆括号“()”也可作为一种运算符使用,这就是,强制类型转换运算符,,它的作用是将表达式或变量的类型强制转换成为所指定的类型。,C,语言程序中进行算术运算时,需要注意数据类型的转换。有两种数据类型转换方式,即隐式转换和显式转换。隐式转换是在对程序进行编译时由编译器自动处理的。,在,C,语言中只有基本数据类型(即,char、,int,、long,和,float),可以进行隐式转换。其余的数据类型不能进行隐式转换。强制类型转换运算符来进行显式转换。强制类型转换运算符的一般使用形式为:,(类型)表达式,例如:需要在外部存储器(,xdata,),中定义一个字符型指针变量,xp,,,并赋初值0,xC000,,可以写成:,xp,=(char,xdata,*)0 xC000;,这种方法特别适合于用标识符来存取地址。,12,sizeof,运算符,C,语言中提供了一种用于求取数据类型、变量以及表达式的字节数的运算符:,sizeof,,,该运算符的一般使用形式为:,sizeof,(,表达式)或,sizeof,(,数据类型),应该注意的是,,sizeof,是一种特殊的运算符,不要错误地认为它是一个函数。实际上,字节数的计算在程序编译时就完成了,而不是在程序执行的过程中才计算出来的。例如:,int,a=,sizeof,(float);,执行这条命令的结果是把4赋给了整型变量,a,,这意味着一个单精度数存储时占有4个字节内存。,7.3,C51,程序设计,7.3.1表达式语句,C,语言是一种结构化的程序设计语言,它提供了十分丰富的程序控制语句。表达式语句是最基本的一种语句。在表达式的后边加一个分号“;”就构成了表达式语句。,表达式语句也可以仅由一个分号“;”组成,这种语句称为空语句。空语句是表达式语句的一个特例。空语句在程序设计中有时是很有用的,当程序在语法上需要有一个语句,但在语义上并不要求有具体的动作时,便可以采用空语句。空语句通常有两种用法:,1在程序中为有关语句提供标号,用以标记程序执行的位置。,2在用,while,语句构成的循环语句后面加一个分号,形成一个不执行其它操作的空循环体。,7.3.2复合语句,复合语句是由若干条语句组合而成的一种语句,它是用一个大括号“”将若干条语句组合在一起而形成的一种功能块。复合语句不需要以分号“;”结束,但它内部的各条单语句仍需以分号“;”结束。复合语句的一般形式为:,局部变量定义;,语句1;,语句2;,。,语句,n;,复合语句在执行时,其中的各条单语句依次顺序执行。整个复合语句在语法上等价于一条单语句,因此在,C,语言程序中可以将复合语句视为一条单语句。复合语句允许嵌套,即在复合语句内部还可以包含别的复合语句。,通常复合语句都出现在函数中,实际上,函数的执行部分(即函数体)就是一个复合语句。复合语句中的单语句一般是可执行语句,此外还可以是变量的定义语句(说明变量的数据类型)。用复合语句内部变量定义语句所定义的变量,称为该复合语句中的局部变量,它仅在当前这个复合语句中有效。利用复合语句将多条单语句组合在一起,以及在复合语句中进行局部变量定义是,C,语言的一个重要特征。,7.3.3流程控制语句,选择结构,if,语句,if,语句有三种形式:单分支选择,if,语句、双分支选择,if,语句和多分支选择,if,语句。,(1)单分支选择语句,If(,条件表达式)语句,其含义为:若条件表达式的结
展开阅读全文