版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第4章单片机的C51程序设计
吴政江制作
贵州电子信息职业技术学院贵州省人才培养优秀单位4.1C51程序的结构特点4.2C51语法基础4.3C51的数据类型、存储类型及常量与变量4.4C51对单片机主要资源的定义4.5C51的基本运算4.6C51的构造数据类型4.7C51的流程构造语句4.8C51的函数4.9指针4.10C51程序设计举例实训四:单片机控制流水灯(C51程序)实训五:计数器的C51程序设计与制作小结习题与思考题4.1C51程序的结构特点
4.1.1C语言与汇编语言的比较单片机的C51编程与汇编语言编程相比,具有以下优点。(1)对单片机的指令系统不要求有任何的了解,就可以用C语言直接编程操作单片机。(2)寄存器分配、不同存储器的寻址以及数据类型等细节完全由编译器自动管理。(3)程序有规范的结构,可分成不同的函数,可使程序结构化。(4)库中包含许多标准函数,具有较强的数据处理能力,使用十分方便。(5)具有方便的模块化编程技术,使已编好的程序很容易移植。4.1.2C51程序的结构特点
举例:设单片机AT89C51的P1.0口接有一个发光二极管,如图4-1所示。试用C51编程使该发光二极管间隔1s亮灭闪动。LEDVccAT89C51P1.0R1图4-1驱动发光二极管#include<reg51.h>//包含51系列单片机头文件#defineuintunsignedint//宏定义sbitled1=P1^0;//声明单片机P1口的第一位voiddelayms(uint);//声明延时子函数voidmain()//主函数{While(1)//大循环{led1=0;/*点亮接在P1.0引脚上的LED*/delayms(1000);//延时1秒led1=1;/*关闭接在P1.0引脚上的LED*/delayms(1000);//延时1秒}}voiddelayms(uintxms)//延时x毫秒子函数{uinti,j;for(i=xms;i>0;i--)/*i=xms即延时约xms毫秒*/for(j=110;j>;j--);}由以上例子可看出C51程序结构具有以下特点:(1)C语言程序是由函数构成的。(2)一个函数由两部份组成。①函数首部,即函数的第一行。②函数体,即函数首部下面的大括号“{}”内的部分。函数体一般包括:a.声明部分:在这部分中定义所用到的变量,如“sbitled1=P1^0;”。b.执行部分:由若干个语句组成。(3)一个C语言程序,总是从main()函数开始执行的,而不管物理位置上这个main()放在什么地方。(4)C语言源程序的前面几行通常是以“#”开头的预处理命令。预处理命令包括文件包含(include)命令、宏(define)命令以及条件编译命令等。(5)C语言区分大小写。如将“include”写成“INCLUDE”就会编译出错。(6)C语言书写的格式自由,可以在一行写多个语句,也可以把一个语句写在多行。(7)每个语句和资料定义的最后必须有一个分号“;”,分号“;”是C语句的必要组成部分,即语句结束标志。但预处理命令、函数头和花括号“}”之后不能加分号“;”。(8)可以用/*……*/的形式为C程序的任何一部分作注释。C51也支持C++风格的注释,即用“//”引导的后面的语句是注释。例如:P1_0=!P1_0;//取反P1.0这种风格的注释,只对本行有效,所以不会出现上面的问题,而且书写也比较方便。因此,程序在只需要一行注释的时候,建议采用这种格式。(9)一个C语言源程序可以由一个或多个源文件组成。4.2C51语法基础
4.2.1C语言词汇(1)标识符在程序中使用的变量名、函数名、标号等统称为标识符。C语言规定,标识符只能是字母(A~Z,a~z)、数字(0~9)、下划线(_)组成的字符串,并且第一个字符必须是字母或下划线。①标准C语言不限制标识符的长度,但它受各种版本的C语言编译系统限制,同时也受到具体机器的限制。②在标识符中,大小写是有区别的。③标识符虽然可由程序员随意定义,但标识符是用于标识某个量的符号。④标识符不能使用系统保留的关键字。(2)关键字(也叫保留字)①数据类型关键字。用于定义或说明变量、函数或其他数据结构的类型。主要有char,double,float,int,long,short,signed,struct,union,unsigned,void,enum等12个。②控制语句关键字。用于表示一个语句的功能。主要有break,case,continue,default,do,else,for,goto,if,return,switch,while等12个。③存储类型关键字。用于说明变量或函数的存储类型。主要有auto,extern,register,static等4个。④预处理命令关键字。用于表示一个处理命令。主要有include、define等2个。⑤其他关键字。主要有const,sizeof,typedef,volatile等4个。(3)运算符C语言中含有相当丰富的运算符。如强制类型转换运算符、算术运算符、关系运算符、逻辑运算符以及位运算符等。运算符与变量、函数一起组成表达式,表示各种运算功能。运算符由一个或多个字符组成。(4)分隔符①逗号分隔符。
②空格分隔符。4.2.2编译预处理
编译预处理命令概念:计算机将C语言编译为机器语言时进行的预处理。这些命令只在编译时有效,不是计算机运行的可执行语句。编译预处理命令以“#”开头,末尾不加分号,包括头宏命令、文件包含命令、条件编译命令等。
(1)宏命令作用:用标识符来代表一个字符串,系统在编译之前自动将标识符替换为字符串。主要用于定义常量。宏定义的标识符(常量)一般用大写字母,以便与变量相区别。定义形式:#define标识符字符串例如:#definePI3.14/*后续程序中所有的PI都用3.14代替。即凡是出现PI的地方即表示3.14,这样做有利于阅读程序和修改程序。*/(2)文件包含
文件包含:指在一个文件中将另一个文件的全部内容包含进来,通常用来将程序中用到的系统函数、宏标识符、自定义函数等的文件包含进来。被包含的文件也叫头文件(以“.h”为扩展名的文件)。
格式:#include<文件名>或#include“文件名”在KeilC51中常用的包含文件(头文件)有以下三种:
①reg51.h头文件。reg51.h是对51子系列单片机的特殊功能寄存器进行定义的头文件,使用汇编语言中的特殊功能寄存器名称,将各个特殊功能寄存器定义为该寄存器的直接地址,在C语言中可以通过寄存器名称直接对这些寄存器进行操作,特殊功能寄存器名称全部使用大写。reg51.h没有对单片机的四个输入输出端口进行位定义,如果程序中需要对并行端口进行位操作,可以使用regx51.h。对于52系列单片机,相应的头文件为reg52.h或regx52.h。②stdio.h头文件。stdio.h是标准输入输出库函数头文件。该库函数文件是定义计算机键盘输入与计算机屏幕显示的库函数,单片机本身无需这些库函数,但为了方便利用计算机调试程序,需要包含该头文件。常用的标准输入、输出库函数有以下两种:a.printf(格式控制,输出列表);。该函数按指定格式在屏幕上显示对应输出项的值。b.scanf(格式控制,地址列表);。该函数接收计算机键盘输入的数据并赋值给对应的变量。例如:intx=3;chary[3]=“abc”;printf(“x=%d,y=%3s\n”,x,y);scanf(“%d,%c\n”,&x,&y);printf(“x=%d,y=%3s\n”,x,y);其中,格式控制必须包含在一对双引号内,包括格式说明符(%d)、普通字符(x=,y=)和转义控制符(\n)三种类型。格式说明符前必须用百分号“%”。常用的格式说明符的含义如表4-1所示。表4-1常用格式字符的含义格式字符说明附加格式字符说明d带符号的十六进制数m数据长度s字符串n截取字符的个数c一个字符f小数形式的实数nn位小数常用的转义控制符有两个:\n:换行。\r:回车。他的前必须用反斜杠“\”。再如,在计算机屏幕上打印99乘法口诀表。参考程序如下所示:/*cfb.c*/#include<reg51.h>//包含51系列单片机头文件#include<stdio.h>//包含基本输入、输出头文件voidcominit() //设置定时器、串行通信函数{SCON=0x50;//设置串行口控制寄存器
TMOD|=0x20;//设置定时器方式寄存器
TH1=0xf3;//设置定时器1(T1)高8位的初值
TR1=1;//启动定时器1TI=1;//置位发送标志位}voidmain(void)//主函数{unsignedinti,j;//定义无符号整型变量i与jcominit();//调用设置定时器、串行通信函数for(i=1;i<=9;i++)//外循环{for(j=1;j<=i;j++)//内循环 printf("%dX%d=%d",j,i,i*j);//计算机屏幕上打印一行乘法口诀表 printf("\n");//换行打印}}在keilC51中,为了借助计算机键盘与屏幕调试程序,需要模拟单片机串行口与计算机键盘与计算机屏幕进行通信。因而需要设置定时器/计数器与串行通信,“voidcominit()”函数就是为此目的而写的。程序调试运行结果如下所示:1X1=11X2=22X2=41X3=32X3=63X3=91X4=42X4=83X4=124X4=161X5=52X5=103X5=154X5=205X5=251X6=62X6=123X6=184X6=245X6=306X6=361X7=72X7=143X7=214X7=285X7=356X7=427X7=491X8=82X8=163X8=244X8=325X8=406X8=487X8=568X8=641X9=92X9=183X9=274X9=365X9=456X9=547X9=638X9=729X9=81③用户自定义标题文件。用户将自己常用的宏定义、条件编译、图片代码、数据表格等组成一个文件,然后在各个源程序中用“#include”命令包含进来,无需重复定义。4.3C51的数据类型、存储类型及常量与变量
4.3.1C51的数据类型C51的数据类型大体上可以分为基本数据类型、构造数据类型和空类型等三种。其中基本数据类型又可分为位型、无符号字符型、有符号字符型、无符号整型、有符号整型、无符号长整型、有符号长整型、浮点型及双精度实型等九种类型。它们的符号、长度、值域等如表4-2所示。表4-2C51的数据类型数据类型数据类型名称长度/bit长度/Byte表示数的范围bit或sbit位型1—0,1unsignedchar无符号字符型810~255signedchar有符号字符型81-128~+127unsignedint无符号整型1620~65535signedint有符号整型162-32768~+32767unsignedlong无符号长整型3240~4294967295(0~232-1)signedlong有符号长整型324-2147483648~+2147483647(-231~231-1)float单精度实型(浮点型)324±3.4e-38~±3.4e+38(相当于6位有效数字)double双精度实型648±1.7e-38~±1.7e+38(相当于10位有效数字)4.3.2C51的数据存储类型(1)数据存储类型C51允许将变量或常量定义成不同的存储类型,以使单片机访问不同的存储空间。主要包括片内直接寻址型、片内位寻址型、片内间接寻址型、片外分页寻址型、片外间接寻址型以及代码型等六种类型,它们和单片机的不同存储区相对应。如表4-3所示。表4-3C51存储类型与MCS-51单片机存储空间的对应关系存储类型存储类型名称长度/bit长度/Byte值域范围与MCS-51单片机存储空间的对应关系data片内直接寻址型810~255直接寻址片内低128字节数据存储器RAMbdata片内位寻址型8132~47按位或字节寻址片内RAM的20H~2FH地址空间idata片内间接寻址型810~255间接寻址片内RAM的00H~FFH地址空间pdata片外分页寻址型810~255分页寻址256字节片外RAM,对应MOVX@Rixdata片外间接寻址型1620~65535寻址64K字节片外RAM,对应MOVX@DPTRcode代码型1620~65535寻址64K字节ROM,对应MOVC@DPTR(2)变量存储类型定义举例变量的存储类型通常与数据类型一起使用。先说明数据类型,再说明存储类型。现举例如下:①chardatavar1;//字符型变量var1被定义为data型,被分配在片内RAM中的低128字节中。②bitbdataflags;//位变量flags被定义为bdata型,定位在片内RAM中的位寻址区。③floatidatax,y,z;/*浮点型变量x、y和z被定义为idata存储类型,定位在片内RAM中,并只能用间接寻址方式进行访问。*/④unsignedintpdatadimension;/*无符号整型变量dimension被定义为pdata型,定位在片外数据存储区,相当于用MOVX@Ri访问。*/⑤unsignedcharxdatavector[10][4][4];/*无符号字符型三维数组变量vector[10][4][4]被定义为xdata存储类型,定位在片外RAM中,占据10×4×4=160个字节,相当于用MOVX@DPTR访问。*/(3)存储模式如果在变量定义时略去存储类型标志符,则由编译器(如KeilC51)自动默认存储类型。默认的存储类型进一步由SMALL、COMPACT和LARGE存储模式指令限制。存储模式的有关说明如表4-4所示。表4-4存储模式及说明存储模式模式名称说
明SMALL小模式参数及局部变量放入可直接寻址的片内存储器(最大128字节,默认存储类型是data),因此访问十分方便。另外所有对象,包括栈,都必须嵌入片内RAM。栈长很关键,因为实际栈长依赖于不同函数的嵌套层数。COMPACT一般模式(中模式)参数及局部变量放入分页片外存储区(最大256字节,默认存储类型是pdata),通过寄存器R0和R1间接寻址,栈空间位于内部数据存储器中。LARGE大模式参数及局部变量直接放入片外数据存储区(最大64KB字节,默认存储类型是xdata),使用数据指针DPTR来进行寻址。用此数据指针访问的效率低,尤其是对二个或多个字节的变量,这种数据类型的访问机制直接影响代码的长度,另一个不便之处在于这种数据指针不能对称操作。4.3.3常量与变量(1)常量在程序运行过程中,其值不能被改变的量称为常量,如数字、字符等。每种数据类型的数值都有常量。字符型常量用单引号括起来,字符串常量用双引号括起来,十六进制数常量用“0x+数值”表示。①直接常量(也叫字面常量)。如12、0、0xCE、‘A’、“GUIZHOU”等。②符号常量。符号常量即是用一个标识符来代替一个常量。符号常量通常用前面介绍的宏命令define来定义。如:#definetscr_init0x40#definetmodh_init0#definetmodl_init250也可通过const关键字来定义的符号常量。定义形式:数据类型const标识符=数字如:intconstPI=3;区别:用define定义的常量不占任何存储空间,在编译时直接用对应的数据代替其常量名称参与运算。而用const定义的常量则会占去单片机ROM区的内存,占去的空间大小为其定义数据类型所占空间的大小,如上面定义的PI常量占2个字节的空间。(2)变量在程序运行过程中,其值可以被改变的量称为变量。每个变量都必须有变量名,变量名是标识符,必须满足用户标识符的要求。变量必须先定义后使用,定义变量的目的是说明变量的数据类型,以便为变量分配相应的存储单元。在程序使用变量前最好给变量赋初值,不赋初值的数值型变量其初值为0。变量在定义的同时可以赋初值。如:[static]intx,y=2,j=5;floatsum;以上两条语句定义了x、y、j三个静态整型变量和一个浮点型变量sum,并且给变量y赋初值2,j赋初值5,没有给变量x赋初值,其初值默认为0。其中的存储类型在需要特别声明的时候才需要,否则可以省略。同类变量可以共用一个数据类型说明符,各个变量之间用逗号隔开,最后以分号结束。这三个整型变量x、y、j在后面的程序中可以存放整型数据。浮点型变量sum可以存放一个浮点型数据的值。4.4C51对单片机主要资源的定义
4.4.1使用关键字定义特殊功能寄存器(SFR)SFR及其可位寻址的位是通过关键字sfr和sbit来定义的,这种方法与标准C不兼容,只适用于C51。(1)用sfr定义特殊功能寄存器(SFR)的字节地址①格式:sfr寄存器变量名称=地址值;②功能:将右边的地址赋值给左边的寄存器变量名称。③举例:a.sfrPSW=0xD0;//定义程序状态字寄存器PSW的地址为D0Hb.sfrSCON=0x98;//定义串行口控制寄存器SCON的地址为98Hc.sfrP0=0x80;//定义P0口的地址为80Hd.sfrTMOD=0x89;//定义定时器/计数器方式控制寄存器TMOD的地址为89H(2)用sbit定义特殊功能寄存器(SFR)的位地址①格式:sbit的用法有三种格式,分别介绍如下。a.sbit位变量名称=位地址值;b.sbit位变量名称=SFR名称^变量位地址值;c.sbit位变量名称=SFR地址值^变量位地址值;②功能:将右边的位地址赋值给左边的位变量名称。③举例:a.sbitCY=0xD7;//定义进位标志CY的地址为D7Hb.sbitAC=PSW^6;//定义辅助进位标志AC为PSW的第6位,其中PSW必须先用sfr定义好c.sbitRS0=0xD0^3;//定义RS0的地址为D3H(即D0H单元的第3位)注意:用sfr和sbit定义的SFR必须位于函数外,一般放在程序的开头。
4.4.2通过头文件访问特殊功能寄存器(SFR)
头文件:以“.h”为扩展名的文件。C51编译器给出的头文件已经给出了MCS-51单片机中的SFR及其可位寻址位的定义。并且KeilC51编译器将这些头文件按单片机的不同生产公司、不同型号分别存放在KeilC51的INC子目录下,在程序中只需引用这些头文件即可实现对SFR的访问和控制。头文件通常有reg51.h,reg52.h,math.h,ctype.h,stdio.h,stdlib.h,absacc.h,intrins.h等八个。但常用的却只有reg51.h或reg52.h,math.h等二个。reg51.h或reg52.h是定义51单片机或52单片机特殊功能寄存器和位寄存器的,这两个头文件中大部分内容是一样的,52单片机比51单片机多一个定时器T2,因此,reg52.h中也就比reg51.h多几行定义T2的内容。math.h是定义常用数学运算的,比如求绝对值、求方根、求正弦或余弦等,该头文件中包含有各种数学运算函数,当我们需要使用时可以直接调用它的内部函数。在代码中引用头文件,其实际意义就是将这个头文件中的全部内容放到引用头文件的位置,从而免去我们每次编写同类程序时都要将头文件中的语句重复编写。打开reg51.h,其全部内容见教材所示。举例如下:#include<reg51.h>//使用的单片机为AT89C51main(){TL0=0xb0;//访问定时器0,设置时间常数TH0=0x3c;TR0=1;//启动定时器0┅}4.4.3扩展I/O端口或片外RAM的直接访问
扩展的片外RAM或I/O端口需要用户自己先定义后才能在语句或函数中使用。现举例如下:#include<absacc.h>/*包含头文件absacc.h,其内部将XBYTE定义为一个指针,指向外部数据存储器RAM的零地址单元*/#definePAXBYTE[0xffec]//将PA定义为外部I/O口,地址为0xffecmain(){PA=0x3a;//将数据3AH写入地址为0xffec的存储单元或I/O端口}4.4.4定义和使用位变量
C51使用关键字“bit”来定义位变量。格式:bit变量名称;功能:将变量名称定义为位型变量。例:bitlock;//将lock定义为位变量bitdirention;//将dirention定义为位变量函数既可以有bit类型的参数,也可以有bit类型的返回值。例如:bitfunc(bitb0,bitb1){bita;┅return(a);}4.5C51的基本运算
4.5.1C51的算术运算(1)基本的算术运算符①+:加法运算符。②-:减法运算符。③*:乘法运算符。④/:除法或求模运算符。⑤%:取余运算符。(2)自增、自减运算符①++:自增运算符。②--:自减运算符。例如:++j、j++、--j、j--注意:++和--运算符只能用于变量,不能用于常量和表达式。++j表示先加1,再取值;而j++表示先取值,再加1。自减运算也是如此。(3)算术表达式和运算符的优先级与结合性①算术表达式就是用算术运算符和括号将运算对象连接起来的式子。例如:(2a+3b)*c/d。②C51规定了算术运算符的优先级为先乘除和取模,后加减,括号最优先。③C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。算术运算符均为左结合性,即先左后右。例如表达式x-y+z,则y应先与“-”号结合,执行x-y运算,然后再执行+z的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。最典型的右结合性运算符是赋值运算符。如x=y=z,由于“=”的右结合性,应先执行y=z,再执行x=(y=z)运算。④不同数据类型间的转换。其一是自动类型转换,即在程序编译时,由C编译器自动进行数据类型转换。其二是使用强制类型转换运算符。语句形式为:(类型说明符)(表达式)。功能:把表达式的运算结果强制转换成类型说明符所表示的类型。例如:inta,b;//a、b为整数(double)(a+b);//将a+b强制转换成double数据类型4.5.2C51的关系运算(1)关系运算符及其优先级关系运算符也叫比较运算符,C51提供了以下6种关系运算符。①<:小于运算符。④>=:大于等于运算符。②<=:小于等于运算符。⑤==:等于运算符。③>:大于运算符。⑥!=:不等于运算符。在以上运算符中,<、<=、>、>=这四个运算符的优先级相同,处于高优先级;==和!=这两个运算符的优先级也相同,处于低优先级。此外,关系运算符的优先级低于算术运算符的优先级,而高于赋值运算符的优先级。(2)关系表达式关系表达式:用关系运算符将运算对象连接起来的式子。如:a>b、(a=4)<(b=3)等。关系表达式的值为逻辑值,其结果只能是真和假两种值之一。C51中用1表示真,用0表示假。4.5.3C51的逻辑运算(1)逻辑运算符及其优先级逻辑运算是对变量进行逻辑与运算、或运算及非运算。①&&:逻辑与运算符。②||:逻辑或运算符。③!:逻辑非运算符。其中非运算的优先级最高,而且高于算术运算符;或运算的优先级最低,低于关系运算符,但高于赋值运算符。(2)逻辑运算表达式逻辑运算表达式:用逻辑运算符将运算对象连接起来的式子。例如:(a>b)||c&&!d,表示a大于b的值跟c与d非的值相或。逻辑表达式的值与关系表达式的值一样,也是逻辑量,即真或假。4.5.4C51的位运算位运算的操作对象只能是整形和字符型数据,而不能是实型数据。①&:按位与运算符,两个字符或整数按位进行逻辑与运算。例如:var3=var1&var2。②|:按位或运算符,两个字符或整数按位进行逻辑或运算。例如:var3=var1|var2。③^:按位异或运算符,两个字符或整数按位进行逻辑异或运算。例如:var3=var1^var2。④~:按位取反运算符,两个字符或整数按位进行逻辑非运算。例如:var1=~var2。⑤<<:左移运算符,字符或整数按位进行逻辑左移运算。例如:var1=var2<<4。⑥>>:右移运算符,字符或整数按位进行逻辑右移运算。例如:var1=var2>>6。4.5.5C51的赋值运算(1)赋值运算符赋值符号“=”完成的操作即为赋值运算,它是右结合性,且优先级最低。(2)赋值表达式将一个变量与表达式用赋值号连接起来就构成赋值表达式。形式如下:变量名=表达式功能:将“=”右边表达式的值赋给“=”左边的一个变量。例如:a=(b=4)+(c=6),该表达式的值为10,变量a的值也为10。(3)赋值的类型转换规则在赋值运算中,当赋值运算符“=”两侧的类型不一致时,系统自动将右边表达式的值转换成左侧变量的类型,再赋给该变量。转换规则如下。①实型数据赋给整型变量时,舍弃小数部分。②整型数据赋给实型变量时,数值不变,但以IEEE浮点数形式存储在变量中。③长字节整型数据赋给短字节整形变量时,实行截断处理。如将long型数据赋给int型变量时,将long型数据的低两字节数据赋给int型变量,而将long型数据的高两字节的数据丢弃。④短字节整型数据赋给长字节整型变量时,进行符号扩展。如将int型数据赋给long型变量时,将int型数据赋给long型变量的低两字节,而将long型变量的高两字节的每一位都设为int型数据的符号值。(4)复合赋值运算符赋值符号前加上其它运算符即构成复合运算符。+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=。其功能是先进行加、减、乘、除、取余、与、或、异或、左移以及右移运算后再进行赋值操作。例如:a+=b;//等价于a=(a+b),赋值表达式加上分号即“a+=b;”也叫赋值语句x*=a+b;//等价于x=x*(a+b)a&=b;//等价于a=(a&b)a<<=4;//等价于a=(a<<4)4.6C51的构造数据类型
4.6.1数组
数组是同类型数据的一个有序集合。它必须由具有相同数据类型的元素构成,这些数据的类型就是数组的基本类型。例如,若数组中的所有元素都是整型,则该数组称为整型数组,若所有元素都是字符型,则该数组称为字符型数组。数组用一个名字来标识,称为数组名。数组中各元素的顺序用下标来标识,下标为n的元素可以表示为:数组名[n]。改变[]中的下标就可以访问数组中所有的元素。但应注意,数组必须先定义,后使用。根据下标的多少,可将数组分为一维数组、二维数组和多维数组,它们的定义形式不同。(1)一维数组一维数组是指由只具有一个下标的数组元素组成的数组。定义形式如下:类型说明符数组名[元素个数];例如:intdemol[10];//定义一个名为demol的整型数组,数组包含10个元素在定义时赋初值的方法:①在定义数组时对数组的全部元素赋予初值。例如:inta[5]={1,2,3,4,5};//给全部元素赋值,a[0]=1,a[1]=2,a[2]=3,a[3]=4,a[4]=5。②只对数组的部分元素初始化。例如:intb[6]={1,2};//给部分元素赋值,b[0]=1,b[1]=2,b[2]=b[3]=b[4]=b[5]=0。③在定义数组时对数组的全部元素不赋初值,则数组元素值均被初始化为0。④可以在定义时不指明数组元素的个数,而根据赋值部分由编译器自动确定。例如:ucharBitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};这相当于定义了一个BitTab[6]这样一个数组。⑤可以为数组指定存储空间。若未指定空间时,则将数组定义在内部RAM中,而当用关键字code定义时,将数组元素定义在ROM空间中。例如:ucharcodeBitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};这种方式适用于编程中不需要改变内容的场合,如显示用LED数码管的字形码等是很合适的。⑥C语言并不对越界使用数组进行检测。例如上例中数组的长度是6,其元素应该是从BitTab[0]到BitTab[5],但是如果你在程序中写上BitTab[6],编译器并不会认为这有语法错误,也不会给出警告(其他语言如BASCI等则有严格的规定,这种情况将视为语法错误),因此,编程者必须自己小心确认这是否是你需要的结果。(2)二维数组或多维数组数组的下标具有两个或两个以上,则称为二维数组或多维数组。定义二维数组的一般形式:类型说明符数组名[行数][列数];例如:floatdemo2[3][4];//demo2数组有3行4列共12个实型元素。二维数组既可以在定义时进行整体初始化,也可在定义后单个地进行赋值。例如:inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};//全部初始化结果为a[0][0]=1,a[0][1]=2,a[0][2]=3,a[0][3]=4,a[1][0]=5,a[1][1]=6,a[1][2]=7,a[1][3]=8,a[2][0]=9,a[2][1]=10,a[2][2]=11,a[2][3]=12。intb[3][4]={{1,2,3,4},{5,6,7,8},{}};//部分初始化(3)字符数组若一个数组的元素是字符型的,则该数组就是一个字符数组。例如:chara[8]={“JiXie”};//字符数组charadd[3][6]={“weight”,“height”,“width”};//字符串数组4.6.2结构(1)结构类型的定义(有三种方法)①先定义结构类型,再定义结构变量名定义结构类型的一般格式为:struct结构类型名{结构元素表;//与定义基本数据类型相似};例如:structdate{intyear;charmonth;charday;};定义好一个结构类型之后,就可以用它来定义结构变量。一般格式为:struct结构名结构变量名1,结构变量名2,…,结构变量名n;例如,可以用结构date来定义两个结构变量d1和d2。其格式为:structdated1,d2;//结构变量d1和d2都具有structdate的结构。②在定义结构类型的同时定义结构变量名这种方法是将方法1的两个步骤合在一起,一般格式为:struct结构类型名{结构元素表;//与定义基本数据类型相似}结构变量名1,结构变量名2,…,结构变量名n;例如,对于上述日期结构变量也可按以下格式定义:structdate{intyear;charmonth;charday;}d1,d2;③直接定义结构变量这种方法可以省掉结构名,又称为无名结构,一般格式为:struct{结构元素表}结构变量名1,结构变量名2,…,结构变量名n;例如,上述日期结构变量可以按以下格式定义:struct{intyear;charmonth;charday;}d1,d2;
第③种方法与第②种方法十分相似,所不同的只是第③种方法中省略了结构名“date”。这种方法一般只用于定义几个确定的结构变量的场合。(2)结构类型变量的引用使用成员运算符“.”实现对结构成员的引用。引用格式:结构变量名.结构元素例如,d1.year表示结构变量d1中的元素year,d2.day表示结构变量d2中的元素day等。如果一个结构变量中的结构元素又是另外一个结构变量,即出现结构的嵌套时,则需要采用若干个成员运算符,一级一级地找到最低一级的结构元素,而且只能对这个最低级的结构元素进行访问。对结构变量中的各个元素可以像普通变量一样进行赋值、存取和运算。例如:d1.year=2009;sum=d1.day+d2.day;d1.month++;m1.time.hour=0x22;其中成员运算符“.”的优先级别最高,因此d1.month++是对d1.month进行自加运算,而不是先对month进行自加运算。m1.time.hour=0x22是对嵌套结构类型中最低一层的结构元素进行访问。4.6.3联合(1)联合与结构的比较与结构相似,在一个联合中也可以包含多个不同类型的数据元素。但在内存的分配上,联合与结构有着本质的区别。结构变量所占用的内存长度是其中各个元素所占内存长度的总和,而联合变量所占用的内存长度是其中最长元素的长度。因为联合变量是采用所谓的“覆盖技术”对内存进行分配的。这种技术可使不同的变量分时使用同一个内存空间,从而提高内存的利用效率。即联合为程序提供了一个不关心机器结构而又能在同一存储区处理不同数据类型的方法。例如,可将一个float型变量、一个int型变量、一个char型变量放在同一个地址开始的内存单元中,如图4-3所示。以上三个变量在内存中的字节数不同,但却都从同一地址开始存放,这就是所谓的“覆盖技术”。floatiintjchark起始地址图4-3联合中变量的存储方法(2)联合类型的定义(与结构相似,联合也有三种定义方法)。①先定义联合类型,再定义联合变量名定义联合类型的一般格式为:union联合类型名{联合成员说明;//与定义基本数据类型相似};其中“联合成员说明”为该联合中的各个成员(又称为联合的域),由于联合可以由不同类型的数据组成,因此对联合中的各个成员都要进行类型说明。例如,一个名为date的联合类型可以定义如下:uniondate{intival;floatfval;
charsval;
};定义好一个联合类型之后,就可以用它来定义联合变量了。其定义格式为:union联合类型名联合变量名1,联合变量名2,…,联合变量名n例如,可以用联合date来定义三个结构变量a、b、c。其格式为:uniondatea,b,c;联合变量a、b、c都具有uniondate类型的结构,即它们都是由一个整型数据、一个浮点型数据和一个字符型数据所组成的。并且,变量a,b,c将足够大,使其能够容纳这三种类型中的最大者,具体的长度与操作无关。②在定义联合类型的同时定义联合变量名这种方法是将方法①的两个步骤合在一起,一般格式为:union联合类型名{联合成员说明;//与定义基本数据类型相似}变量列表;例如,对于上述date联合变量也可按以下格式定义:uniondate{intival;floatfval;charsval;}a,b,c;③直接定义联合变量这种方法可以省掉联合名,又称为无名联合,一般格式为:union{联合成员说明}结构变量名1,结构变量名2,…,结构变量名n;例如,上述a、b、c联合变量也可以按以下格式定义:union{intival;floatfval;
charsval;
}a,b,c;第③种方法与第②种方法十分相似,所不同的只是第③种方法中省略了联合名“date”。这种方法一般只用于定义几个确定的联合变量的场合。在上例中,如果只需要定义a、b和c而不打算再定义任何别的联合变量,则可省掉联合名“date”。不过为了便于记忆和以备将来进一步定义其他联合变量的需要,一般还是不要省掉联合名为好。(2)联合类型变量的引用与结构变量类似,对联合变量的引用也是通过对其联合元素的引用来实现的。格式:联合变量名.联合元素或联合变量名->联合元素。例如:对于前面定义的联合变量a、b、c,下面的引用方法都是正确的:a.fval/*引用联合变量a中float型元素fval*/b.ival/*引用联合变量b中int型元素ival*/c->sval/*引用联合变量c中char型元素sval*/注意:①在引用联合元素时,要注意联合变量用法的一致性。因为联合类型中定义的各个不同类型的元素都可以分时地赋给变量,而所读取变量的值是最近放入的某一元素的值,因此在表达式中对它进行处理时,必须注意其类型与表达式所要求的类型保持一致,否则将导致程序运行出错。不能只引用联合变量。例如,下面的写法就是错误的:printf(“%f”,a);因为变量a可能是float、int和char三种类型,分别占用不同长度的内存区域,若在引用时仅写联合变量名a,系统将难以确定究竟应该输出哪一个联合元素的值。正确的写法应为:printf(“%f”,a.ival);②联合类型的数据可以采用同一个内存段来存放几种不同类型元素的值,但是在每一瞬时只能存放其中一种类型的元素,而不能同时存放几种。换句话说,每一瞬时只有一个元素在起作用。起作用的是联合中最后一次存放的元素,如果存入了一个新的元素,则上次存入的元素就自动失去作用。例如,对于下列语句:a.fval=100.25;a.ival=200;a.sval=10;在执行以上三条赋值语句之后,只有a.sval是有效的,而a.ival和a.fval都已失去作用。因此在引用联合变量时一定要十分注意当前在联合变量中存放的究竟是哪一个元素。不能直接对联合变量进行赋值,也不能在定义联合变量时对它进行初始化。4.7C51的流程控制语句
4.7.1选择控制语句(有if语句和switch/case语句,用于设计分支结构程序)(1)if语句if语句是用来判定所给定的条件是否满足,再根据判定的结果(真或假)来决定执行给出的两种操作之一。C51提供了三种形式的if语句。①形式1。格式:if(表达式){语句;}功能:如果表达式的结果为真,则执行语句,否则不执行。②形式2。格式:if(表达式){语句1;}else{语句2;}功能:如果表达式的结果为真,则执行语句1,否则执行语句2。③形式3。格式:if(表达式1){语句1;}elseif(表达式2){语句2;}elseif(表达式3){语句3;}…elseif(表达式m){语句m;}else{语句n;}功能:这是if语句的嵌套,即一个if语句中又包含有一个或多个if语句。主要用于多分支选择程序。在if语句的嵌套中应注意if与else的对应关系,else总是与它前面最近的一个if语句相对应。【例4.1】
某浮点数的范围在0.000~9999之间,试编写一个函数返回浮点数的小数点位置。解:此题的基本思路是根据浮点数的4种不同取值范围给出4种不同的返回值。可以约定浮点数的大小在0.000~9.999、10.00~99.99、100.0~999.9、1000~9999之间时,分别返回0、1、2和3。参考程序如下:intftochar(floatvalp){intdotno=0;if(valp<10.00)dotno=0;elseif((valp>=10.0)&&(valp<100.0)dotno=1;elseif((valp>=100.0)&&(valp<1000.0)dotno=2;elseif(valp>=1000.0)dotno=3;returndotno;}根据小数点的位置,即可在实际的单片机系统中显示出浮点数或小数。(2)switch/case语句(用于直接处理多分支选择)switch/case语句的一般形式如下:switch(表达式){case常量表达式1:语句1;break;case常量表达式2:语句2;break;……case常量表达式n:语句n;break;default:语句n+1;}说明:当switch后面括号内的“表达式”的值与某一个case后面的常量表达式的值相等时,就执行此case后面的语句(可以是复合语句),遇到break语句就退出switch语句。若所有的case中的常量表达式的值都没有与表达式的值匹配时,就执行default后面的语句。【例4.2】
AT89C51单片机的P1.1和P1.0引脚接有两只按键,其4种逻辑组合分别点亮由P2.0~P2.3控制的4只LED(高电平点亮),试编程实现此功能。解:参考程序如下:#include<at89x51.h>//包含AT89x51系列单片机的头文件voidmain(){chara;do
{a=P1;
a=a&0x03;//屏蔽掉P1口的高6位
P2=P2&0xf0;//开始4只LED全熄
switch(a){case0:P2=P2|0x01;break;case1:P2=P2|0x02;break;case2:P2=P2|0x04;break;case3:P2=P2|0x08;}}while(1);//循环继续读取按键}4.7.2循环控制语句循环程序可分为“当型”循环程序和“直到型”循环程序两种类型,这与其它语言的循环程序一样。在C51语言中,用来构成循环控制的语句有:while语句、do-while语句、for语句以及if和goto语句等。(1)基于while语句构成的循环采用while语句构成循环结构的一般格式如下:while(条件表达式){内部语句;//内部语句可以是复合语句,也可以为空}意义:当条件表达式的结果为真(非0值)时,程序就重复执行后面的内部语句,一直执行到条件表达式的结果变为假(0值)时为止。也就是说,这种循环结构是先检查条件表达式所给出的条件,再根据检查的结果决定是否执行后面的内部语句。如果条件表达式的结果一开始就为假,则后面的内部语句一次也不会执行。因此属于“当型”循环。图4-4为while语句的执行过程。
假条件表达式内部语句真图4-4while语句的执行过程【例4.3】
使用while语句计算自然数1~100的累加和,并用printf()函数通过单片机的串口显示在终端上。解:参考程序如下:#include<stdio.h>/*包含基本输入输出头文件stdio.h*/真内部语句条件表达式假图4-5do-while语句循环结构的流程图voidmain(){inti,sum=0;i=1;while(i<=100){/*复合语句循环体开始*/sum=sum+i;i++;}/*复合语句循环体结束*/printf(“1+2+…+100=%d\n”,sum);while(1);}(2)基于do-while语句构成的循环do-while语句只能用来实现“直到型”循环,其一般格式如下:do{内部语句;//可以是复合语句}while(条件表达式);意义:先执行给定的循环体语句,然后再检查条件表达式的结果。当条件表达式的值为真(非0值)时,则重复执行循环体语句,直到条件表达式的值变为假(0值)时为止。因此,用do-while语句构成的循环结构在任何条件下,循环体语句至少会被执行一次,这就是“直到型”循环。图4-5给出了这种循环结构的流程图。真内部语句条件表达式假图4-5do-while语句循环结构的流程图【例4.4】实型数组sample存有10个采样值,编写一个函数返回其平均值(即平均值滤波程序)。解:参考程序如下:floatavg(float*sample){floatsum=0;charno=0;do{sum+=sample[no];no++;}while(no<10);return(sum/10);}假初值设定表达式内部语句更新表达式循环条件表达式真图4-6for语句的执行过程示意图(3)基于for语句构成的循环采用for语句构成循环结构的一般格式如下:for([初值设定表达式];[循环条件表达式];[更新表达式]){内部语句;//可以是复合语句}意义:先计算出初值设定表达式的值作为循环控制变量的初值,再检查循环条件表达式的结果,当满足条件时就执行循环体语句并计算更新表达式,然后再根据更新表达式的计算结果来判断循环条件是否满足,只有一直进行到循环条件表达式的结果为假(0值)时才退出循环体。各表达式之间必须用分号“;”进行分隔。for语句的执行过程如图4-6所示。【例4.5】
使用for语句计算自然数1~100的累加和,并用printf()函数通过单片机的串口显示在终端上。解:参考程序如下:#include<aduc812.h>#include<stdio.h>intgetsum(void);voidmain(){SCON=0x50;//如果用KeilC进行模拟调用或使用printf(),必须初始化SCONTMOD=TMOD|0x20;//定时器T1工作方式2,用做波特率控制TH1=0xfd;//9600bps对应T1的时间常数为0xfdTL1=0xfd;TR1=1;//启动T1TI=1;//启动发送,以发送第一个字符printf(“%d\n”,getsum());do{}while(1);}intgetsum(void){intsum=0;intn;for(n=1;n<=100;n++){sum=sum+n;}return(sum);}(4)基于if和goto构成的循环①“当型”循环。采用if和goto可以构成“当型”循环程序,其格式如下:loop:if(条件表达式){内部语句;//可以是复合语句gotoloop;}说明:loop是语句标号,实质是带冒号“:”的标识符,原则上任何一条语句都可以有标号,标号和语句之间用冒号“:”分隔。其执行过程是首先判断条件表达式的值,当条件表达式的值为真(非0值)时,则执行内部语句,遇到gotoloop语句时则无条件返回loop处继续判断条件表达式的值。直到条件表达式的值为假(0值)时才退出循环。需注意的是,条件表达式中条件变量的值必须在内部语句中进行改变,否则就成为死循环程序。②“直到型”循环。采用if和goto也可以构成“直到型”循环程序,其格式如下:loop:{内部语句;//可以是复合语句if(条件表达式)gotoloop;}说明:首先执行内部语句(即循环体),再判断条件表达式的值。若条件表达式的值为真(非0值)时,则执行gotoloop语句,无条件返回loop处继续执行内部语句(即循环体)。当条件表达式的值为假(0值)时就退出循环。显然,条件表达式的值不能一直为真(非0值),否则就成为死循环程序。③goto语句。goto语句是一个无条件转向语句,它的一般形式为:goto语句标号;前已述及,语句标号是一个带冒号“:”的标识符,将goto语句和if语句相结合使用,就可以构成“当型”循环或“直到型”循环结构。【例4.6】
使用goto语句跳出循环结构。本程序采用循环结构来求一个整数的等差数列,该数列满足条件:头四个数的和值为26,积值为880。该数列的公差应为正整数,否则将产生负的项,此外该数列的首项数必须小于5,且其公差也应小于5,否则头四项的和值将大于26。解:参考程序如下:#include<stdio.h>voidmain(){inta,b,c,d,i;for(a=1;a<5;++a){for(d=1;d<5;++d){
b=a+(a+d)+(a+2*d)+(a+3*d);
c=a*(a+d)*(a+2*d)*(a+3*d);if(b==26&&c==880)gotopt;}}pt:for(i=0;i<=10;++i)printf(“%d,”,a+i*d);
printf(“…\n”);while(1);}④continue语句。
在循环结构中还可以使用一种中断语句continue,它的功能是结束本次循环,即跳过循环体中下面尚未执行的语句,把程序流程转移到当前循环语句的下一个循环周期,并根据循环控制条件决定是否重复执行该循环体。continue语句的一般格式为:continue;
continue语句通常和条件语句一起用在由while、do-while和for语句构成的循环结构中,它也是一种具有特殊功能的无条件转移语句,但与goto、break语句不同,continue语句并不跳出循环体,而只是根据循环控制条件确定是否继续执行循环语句。【例4.7】
利用continue语句把10~20之间不能被3整除的数输出。解:参考程序如下:#include<stdio.h>voidmain(){intn;for(n=10;a<=20;n++){if(n%3==0)continue;printf(“%d”,n);}while(1);}4.8C51的函数
4.8.1函数的分类与定义(1)函数的分类①主函数main()。关于主函数main(),我们应该很熟悉了。下面再简要介绍其格式和特点。格式:voidmain()/*注意:后面没有分号*/{总程序从这里开始执行;其他语句;……}特点:无返回值,无参数。
无返回值表示该函数执行完后不返回任何值,上面main前面的void表示“空”,即不返回值的意思。无参数表示该函数不带任何参数,即main后面的括号中没有任何参数,只写“()”就可以了,也可以在括号里写上void,表示空的意思,如voidmain(void)。②普通函数。a.标准库函数。b.用户自定义函数。(2)函数的定义函数定义的一般形式为:函数类型函数名(形式参数列表)形式参数说明{局部变量定义;函数体语句;}其中,“函数类型”说明了自定义函数返回值的类型。返回值的类型可以是基本数据类型(如int、char、float、double等),也可以是指针类型。当函数没有返回值时,则使用标识符void进行说明。若没有指定函数的返回值类型,则默认返回值为整型类型。一个函数只能有一个返回值,该返回值是通过函数中的return语句获得的。“函数名”是用标识符表示的自定义函数的名字,它必须是一个合法的标识符。“形式参数列表”中列出的是在主调用函数与被调用函数之间传递数据的形式参数,形式参数的类型必须加以说明。形式参数可以是基本数据类型的数据、指针类型数据、数组等。在没有调用函数时,函数的形式参数和函数内部的变量未被分配内存单元,即它们是不存在的。如果定义的是无参数函数,可以没有形式参数,但圆括号不能省略。“局部变量定义”是对在函数内部使用的局部变量进行定义。局部变量是定义在函数内部的变量,编译器只在定义该变量的函数范围内给其分配存储空间。一旦调用结束,即刻释放所分配的内存单元。不同函数中的局部变量可以同名,但编译器会给它们分配不同的存储空间。形式参数也是一种局部变量。如果将变量定义在主函数之前,则成为全局变量。在其他函数中不加定义即可使用全局变量,各个函数对全局变量的赋值都会引起全局变量内容的变化,因为各个函数修改的是同一个存储单元的内容。对同一名称变量,如果在某一函数中有对该变量的定义(静态变量除外),则该变量在这个函数中成为局部变量,而在该函数之外是全局变量。“函数体语句”是为完成该函数的特定功能而设置的各种语句。在函数体中可以根据用户自己的需要,设置各种不同的语句。这些语句应能完成所需要的功能。【例4.8】
定义一个计算整数的正整数次幂的函数。解:参考程序如下:intpower(x,n)intx,n;{inti,p;p=1;for(i=1;i<=n;++i)p=p*x;return(p);}这里定义了一个返回值为整型的函数power(),它有两个形式参数:x,n。形式参数的作用是接受从主调用函数传递过来的实际参数的值。上例中形式参数x和n被说明为int类型。大括号以内的部分是自定义函数的函数体。上例中在函数体内定义了两个局部变量i和p,它们均为整型数据。需要注意的是,形式参数的说明与函数体内局部变量的定义是完全不同的两个部分,前者应写在大括号的外面,而后者是函数体的一个组成部分,必须写在大括号里面。(3)返回语句return返回语句用于终止函数的执行,并控制程序返回到调用该函数时所处的位置。返回语句有两种格式:return(变量或表达式);或者return;
①如果return语句后边带有变量或表达式,则要计算该变量或表达式的值,并将该变量或表达式的值作为该函数的返回值返回到主调用函数中去。函数返回值的类型就是该函数的类型,因此在定义一个函数时,函数本身的类型应与return语句中变量或表达式的值的类型一致。如果函数的类型与return语句中变量或表达式的值的类型不一致,则以函数的类型为准。对于数值数据可以自动进行转换,即函数的类型决定返回值的类型。
②若使用不带表达式的第2种形式,则被调用函数返回主调用函数时,函数值不确定。一个函数的内部可以含有多个return语句,但程序仅执行其中的一个return语句而返回主调用函数。
③如果不需要被调用函数返回一个确定的值,则可以不要return语句。在这种情况下,当程序执行到最后一个界限符“}”处时,就自动返回主调用函数。对于不需要有返回值的函数,可以将该函数定义为void类型(空类型)。4.8.2函数的调用(1)函数的调用形式C语言程序中函数是可以互相调用的。所谓函数调用就是在一个函数体中引用另外一个已经定义了的函数,前者称为主调用函数,后者称为被调用函数。函数调用的一般形式如下:函数名(实际参数列表);
“函数名”指出被调用的函数。“实际参数列表”中可以包含多个实际参数,各个参数之间必须用逗号隔开。实际参数的作用是将它的值传递给被调用函数中的形式参数。因此,函数调用中的实际参数与函数定义中的形式参数必须在数量、类型以及顺序上严格保持一致,以便将实际参数的值正确地传递给形式参数。否则在函数调用中会产生意想不到的结果。实际参数可以是常数,也可以是变量或表达式,但要求它们具有确定的值。如果调用的是无参函数,则可以没有实际参数列表,但圆括号不能省略。在C语言中可以采用三种方式完成函数的调用:①函数语句:指在主调函数中将函数调用作为一条语句使用。例如:fun1();这是无参函数,它不要求被调用函数返回一个确定的值,只要求它完成一定的操作。②函数表达式:指在主调用函数中将函数调用作为一个运算对象直接出现在表达式中,这种表达式就称为函数表达式。例如:c=power(x,n)+power(y,m);实际上,这是一个赋值语句,它包含两个函数调用,每个函数调用都有一个返回值,将两个返回值相加的结果赋值给变量c。因此这种函数调用方式要求被调用函数返回一个确定的值。③函数参数:指在主调用函数中将函数调用作为另一个函数调用的实际参数。例如:y=power(power(i,j),k);其中,函数调用power(i,j)放在另一个函数调用power(power(i,j),k)的实际参数列表中,以其返回值作为另一个函数调用的实际参数。这种在调用一个函数的过程中又调用了另外一个函数的方式,称为嵌套函数调用。(2)在主调用函数中对被调用函数的说明与使用变量一样,在调用一个函数之前(包括标准库函数),必须对该函数的类型进行说明,即“先说明,后调用”。函数说明的一般形式:类型标识符被调用的函数名(形式参数列表);其中,“类型标识符”说明了函数返回值的类型。“形式参数列表”中说明各个形式参数的类型。
注意:
①函数的说明与函数的定义是完全不同的。
②如果被调用函数是在主调用函数的前面定义的,或者已经在程序文件的开始处说明了所有被调用函数的类型,在这两种情况下不必再对被用函数进行说明。
③可以将所有用户自定义函数的说明另存为一个专门的头文件,需要时用#i
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论