C语言是国际上广泛流行的计算机高级语言,它是一种源于编写UNIX操作系统的结构化语言,编写的程序具有清晰的层次结构。
C51程序结构具有以下特点:
● 一个C语言源程序由一个或多个源文件组成,主要包括一些C源文件(即后缀名为“.c”的文件)和头文件(即后缀名为“.h”的文件),对于一些支持C语言的汇编语言混合编程的编译器而言,还可能包括一些汇编源程序(即后缀名为“.asm”的文件)。
● 每个源文件至少包含一个main()函数,也可以包含一个main()函数和其他多个函数。头文件中声明一些函数、变量或预定义一些特定值,而函数的实现是在C源文件中。
● 一个C语言程序总是从main()函数开始执行的,而不论main()函数在整个程序中的位置如何。
● 源程序中可以有预处理命令(如include命令),这些命令通常放在源文件或源程序的最前面。
● 每个声明或语句都以分号结尾,但预处理命令、函数头和花括号“{}”后不能加分号。
● 标识符、关键字之间必须加一个空格以示间隔。若已有明显的间隔符,也可不再加空格来间隔。
● 源程序中所用到的变量都必须先声明,然后才能使用,否则编译时会报错。
C源程序的书写格式自由度较高,灵活性很强,有较大的随意性,但是这并不表示C源程序可以随意乱写。为了书写清晰,并便于阅读、理解、维护,在书写程序时最好遵循以下规则。
● 通常情况下,一个声明或语句占用一行。在语句的后面可适量添加一些注释,以增强程序的可读性。
● 不同结构层次的语句从不同的起始位置开始,即在同一结构层次中的语句缩进同样的字数。
● 用“{}”括起来的部分,表示程序的某一层次结构。“{}”通常写在层次结构语句第一字母的下方,与结构化语句对齐,并占用一行。
【例3-1】在此以P_test程序为例,进一步说明C51的程序结构特点及书写规则,程序清单如下:
该程序的作用在项目二中可以通过仿真看出来,下面分析这个C51源程序代码。
第1行至第5行为注释部分。传统的注释定界符使用斜杠—星号(即“/*”)和星号—斜杠(即“*/”)。斜杠—星号用于注释的开始。编译器一旦遇到斜杠—星号(即“/*”),就忽略后面的文本(即使是多行文本),直到遇到星号—斜杠(即“*/”)。简而言之,在此程序中第1行至第5行的内容不参与编译。在程序中还可使用双斜杠(即“//”)来作为注释定界符。若使用双斜杠(即“//”)时,编译器忽略该行语句中双斜杠(即“//”)后面的文本。
第6行和第7行,分别是两条不同的预处理命令。在程序中,凡是以“#”开头的均表示这是一条预处理命令语句。第6行为文件包含预处理命令,其意义是把双引号(即“”)或尖括号(<>)内指定的文件包含到本程序,使其成为本程序的一部分。第7行为宏定义预处理命令语句,表示uint为无符号整数类型。被包含的文件通常是由系统提供的,也可以由程序员自己编写,其后缀名为“.h”。C语言的头文件中包括了各个标准库函数的函数原型。因此,在程序中调用一个库函数时,都必须包含函数原型所在的头文件。对于标准的MCS—51单片机而言,头文件为“reg51.h”,而STC89系列单片机的头文件应为“reg52.h”。
第8行定义了一个BZ的bit(位变量);第9行定义了一个key的bit(位变量)。
第10行定义了一个带参数调用的延时函数,其函数名为“delayms”,调用参数为“uintms”函数的参数为“uinti”。该函数采用了两个层次结构和单循环语句。第11行至第17行表示外部层次结构,其中第11行表示延时函数从此处开始执行;第17行表示延时函数的结束。第14行至第16行表示内部层次结构,其中第15行为执行语句部分。
第18行定义了main主函数,函数的参数为“void”,意思是函数的参数为空,即不用传递给函数参数,函数即可运行。该函数采用了3个层次结构,第19行至第36行为第1层结构;第21行至第35行为第2层结构;第23行至第29行以及第31行至第34行同属于第3层结构,其中第1层为最外层,第3层为最内层。
C51支持的数据类型有位变量型(bit)、字符型(char)、无符号字符型(unsigned char)、有符号字符型(signed char)、无符号整数型(unsigned int)、有符号整数型(signed int)、无符号长整数型(unsigned long int)、有符号长整数型(signed long int)、单精度浮点型(float)、双精度浮点型(double)等,如图3-1所示。
图3-1 C51支持的数据类型
基本类型就是使用频率最高的数据类型,其值不可以再分解为其他类型。C51基本数据类型的长度和范围见表3-1。
表3-1C51基本数据类型的长度和值域
续表
C语言的标识符是用于标志源程序中变量、函数、标号和各种用户定义的对象的名字。C51中的标识符只能是由字母(A~Z、a~z)、数字(0~9)、下划线组成的字符串。其中第1个字符必须是字母或下划线,随后只能取字母、数字或下划线。标识符区分大小写,其长度不能超过32个字符。标识符在命名时,应简单、含义清晰,这样有助于阅读、理解程序,但还要注意,标识符不能用中文。
关键字是由C语言规定的具有特定意义的特殊标识符,有时又称为保留字,这些关键字应当以小写形式输入。在编写C语言源程序时,用户定义的标识符不能与关键字相同。表3-2列出了C51中的一些关键字。
表3-2C51中的一些关键字
续表
1)常量 所谓常量就是在程序运行过程中,其值不能改变的数据。根据数据类型的不同,常量可分为整型常量、字符常量、字符串常量、实数常量、位标量等。
(1)整型常量:整型常量可以用二进制、八进制、十进制和十六进制数表示。表示二进制数时,在数字的前面加上“0b”的标志,其数码取值只能是0和1,如“0b10110010”表示二进制的“10110010”,其值为十制数的1×2 7 +1×2 5 +1×2 4 +1×2 1 =178;表示八进制数时,在数字的前面加上“O”的标志,其数码取值只能是0~7,如“O517”表示八进制的“517”,其值为十进制数的5×8 2 +1×8 1 +7×8 0 =335;表示十六进制时,在数字的前面加上“0x”或“0X”的标志,其数码取值是数字0~9、字母a~f或字母A~F,如“0x3a”和“0X3A”均表示相同的十六进制数值,其值为十进制数的3×16 1 +10×16 0 =58。
无符号整数常量在一个数字后面加上“u”或“U”,如“6325U”;长整数型常量在一个数字后面加上“l”或“L”,如“97L”。无符号长整数型常量在一个数字后面加上“ul”或“UL”,如“25UL”;实数型常量在一个数字后面加上“f”或“F”,如“3.146F”。
(2)字符常量:字符常量是单引号内的字符,如‘a’,‘f’等。不可以显示的控制字符,可以在该字符前加一个反斜杠“\”组成专用转义字符。
(3)字符串常量:字符串常量是由双引号内的字符组成,如“Good”,“P_test”等。当引号内没有字符时,为空字符串。在使用特殊字符时,同样要使用转义字符如双引号。在C语言中,字符串常量是作为字符类型数组来处理的,在存储字符串时,系统会在字符串尾部加上转义字符“\o”,以作为该字符串的结束符。
(4)实数常量:实数常量有十进制和指数两种表示形式。十进制表示的实数由数字和小数点组成,如0.123,32.123,0.0等。整数或小数部分为0时,可以省略但必须有小数点。指数表示的实数为“[±]数字[.数字]e[±]数字”,[]中的内容为可选项,其中内容根据具体情况可有可无,但其余部分必须有,如12e2,8e3,-3.5e-2等。
(5)位标量:位标量的值是一个二进制数。
2)变量 所谓变量就是在程序运行过程中,其值可以改变的数据。要在程序中使用变量,必须先用标识符作为变量名,并指出所用的数据类型和存储模式,这样编译系统才能为变量分配相应的存储空间。定义一个变量的格式:
[<存储模式>]<类型定义>[存储器类型]<标识符>;
在定义格式中,除了类型定义和标识符是必要的,其他都是可选项。存储模式有4种,即自动(auto)、外部(extern)、静态(static)和寄存器(register),默认类型为自动(auto)。
存储器类型与MCS—51单片机实际存储空间的对应关系及其大小见表3-3。
表3-3C51存储类型与MCS—51单片机存储空间的对应关系及其大小
如果在变量定义时省略了存储类型标识符,则编译器会自动选择默认的存储类型。默认的存储类型进一步由SMALL、COMPACT的LARGE存储模式指令限制。
存储模式决定了变量的默认存储类型、参数传递区和无明确存储类型说明变量的存储类型。在SMALL模式下,参数传递是在片内数据存储区中完成的。COMPACT和LARGE模式允许参数在外部存储器中传递。存储器的详细说明见表3-4。
表3-4 存储模式及说明