




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1第章第章c51单片机编程语言单片机编程语言v3.1 3.1 单片机编程语言概述单片机编程语言概述v3.2 c513.2 c51程序设计基础程序设计基础v3.3 3.3 函数、数组、指针的应用函数、数组、指针的应用 v3.4 c513.4 c51程序设计程序设计23.1 3.1 单片机编程语言概述单片机编程语言概述 v5151单片机的编程语言可以是单片机的编程语言可以是汇编语言汇编语言,也可以是,也可以是高级语言高级语言,如,如由由c c语言演变而成的语言演变而成的c51c51语言语言等。等。v汇编语言汇编语言产生的目标代码短,占用的存储空间小,执行速度快,产生的目标代码短,占用的存储空间小,
2、执行速度快,能充分发挥单片机的硬件功能。但对于复杂的应用来讲使用汇编能充分发挥单片机的硬件功能。但对于复杂的应用来讲使用汇编语言编程复杂,程序的可读性和可移植性不强。语言编程复杂,程序的可读性和可移植性不强。v高级语言高级语言产生的目标代码长,占用的存储空间大,执行速度慢。产生的目标代码长,占用的存储空间大,执行速度慢。但这是相对于汇编语言来讲的,其实但这是相对于汇编语言来讲的,其实c c语言在大多数情况下的机语言在大多数情况下的机器代码生成效率和汇编语言相当,但器代码生成效率和汇编语言相当,但可读性可读性和和可移植性可移植性却远远超却远远超过汇编语言,过汇编语言,编程效率编程效率也大大高于汇
3、编语言。也大大高于汇编语言。 3v如果应用系统的存储空间比较小,且对实时性的要求很高,则如果应用系统的存储空间比较小,且对实时性的要求很高,则应选用应选用汇编语言汇编语言。如果系统的存储空间比较大,且对实时性的要。如果系统的存储空间比较大,且对实时性的要求不是很高,则应选用求不是很高,则应选用c51c51语言语言。如果系统中有部分模块对实时。如果系统中有部分模块对实时性的要求很高,而其它模块对实时性的要求不是很高,则可以将性的要求很高,而其它模块对实时性的要求不是很高,则可以将两种语言结合,程序的主体部分使用两种语言结合,程序的主体部分使用c51c51编程,对实时性的要求编程,对实时性的要求高
4、的模块用汇编语言编程,然后将高的模块用汇编语言编程,然后将汇编语言程序模块嵌入到汇编语言程序模块嵌入到c51c51语言程序当中语言程序当中。v无论是高级语言还是汇编语言写的源程序都必须转换成目标程无论是高级语言还是汇编语言写的源程序都必须转换成目标程序,单片机才能执行。目前很多公司都将编辑器、汇编器、编译序,单片机才能执行。目前很多公司都将编辑器、汇编器、编译器、连接器、连接/ /定位器、符号转换程序做成了软件包,称为定位器、符号转换程序做成了软件包,称为集成开发集成开发环境环境,如,如keil uvisionkeil uvision、medwinmedwin等。等。4v使用使用c语言有以下的
5、优点:语言有以下的优点: c 语言具有语言具有结构化结构化和和模块化模块化特点,便于阅读和维护。特点,便于阅读和维护。 c 语言语言可移植性好可移植性好,很多微控制器都支持,很多微控制器都支持c 编译器。功能编译器。功能化的代码能够很方便的从一个工程移植到另一个工程,从而化的代码能够很方便的从一个工程移植到另一个工程,从而减少了开发时间。减少了开发时间。 c 语言编写的程序比汇编语言编写的程序更符合人们的思语言编写的程序比汇编语言编写的程序更符合人们的思考习惯,开发者可以更专心的考虑算法,而不是考虑一些细考习惯,开发者可以更专心的考虑算法,而不是考虑一些细节问题。这样可以减少编程出错的机率,从
6、而节问题。这样可以减少编程出错的机率,从而提高开发效率提高开发效率,减少调试的时间。减少调试的时间。 c 语言和微控制器是语言和微控制器是相对独立的相对独立的,开发者不必知道处理器,开发者不必知道处理器的具体内部结构和处理过程。当基于新型的微控制器开发程的具体内部结构和处理过程。当基于新型的微控制器开发程序时,可以很快上手,减少学习时间和程序开发时间。序时,可以很快上手,减少学习时间和程序开发时间。3.23.2 c51c51程序设计基础程序设计基础5关键字关键字用途用途说明说明_at_地址定位地址定位为变量进行存储器绝对空间地址定位为变量进行存储器绝对空间地址定位alien函数特性声明函数特性
7、声明用以声明与用以声明与pl/m51兼容的函数兼容的函数bdata存储器类型声明存储器类型声明可位寻址的可位寻址的8051内部数据存储器内部数据存储器bit位变量声明位变量声明声明位变量或位类型函数声明位变量或位类型函数code存储器类型声明存储器类型声明8051程序存储器空间程序存储器空间compact存储器模式存储器模式指定使用指定使用8051外部分页寻址数据存储空间外部分页寻址数据存储空间data存储器类型声明存储器类型声明直接寻址的直接寻址的8051内部数据存储器内部数据存储器far存储器类型声明存储器类型声明8051外部数据存储器外部数据存储器idata存储器类型声明存储器类型声明间
8、接寻址的间接寻址的8051内部数据存储器内部数据存储器interrupt中断函数声明中断函数声明定义中断服务函数定义中断服务函数3.2.1 c513.2.1 c51扩展关键字扩展关键字6large存储器模式存储器模式指定使用指定使用8051外部数据存储空间外部数据存储空间pdata存储器类型声明存储器类型声明分页寻址的分页寻址的8051外部数据存储器外部数据存储器_priority_多任务优先声明多任务优先声明规定规定rtx51或或rtx51 tiny的任务优先级的任务优先级reentrant可重入函数声明可重入函数声明定义可重入函数定义可重入函数sbit位变量声明位变量声明声明可位寻址的特殊
9、功能位声明可位寻址的特殊功能位sfr特殊功能寄存器声明特殊功能寄存器声明声明声明8位的特殊功能寄存器位的特殊功能寄存器sfr16特殊功能寄存器声明特殊功能寄存器声明声明声明16位的特殊功能寄存器位的特殊功能寄存器small存储器模式存储器模式指定使用指定使用8051内部数据存储空间内部数据存储空间_task_任务声明任务声明定义实时多任务函数定义实时多任务函数using寄存器组定义寄存器组定义定义定义8051的工作寄存器组的工作寄存器组xdata存储器类型声明存储器类型声明8051外部数据存储器外部数据存储器3.2.1 c513.2.1 c51扩展关键字扩展关键字7位运算符位运算符符号符号含义
10、含义&按位与按位与|按位或按位或按位异或按位异或按位取反。一元运算符按位取反。一元运算符右移操作。右边移出的位舍去,左边移入的位对无符号数补右移操作。右边移出的位舍去,左边移入的位对无符号数补0;对有符号数补符号位对有符号数补符号位8v例:例:unsigned char x=0 x55 ; unsigned char y=0 x37 ; unsigned char z;z=x&y ; 则 z=0 x15z=x|y ; 则 z=0 x77z=xy ; 则 z=0 x62z=x; 则 z=0 xaaz=x1;则 z=0 x2a位运算符举例位运算符举例93.2.2 c513.2.2
11、c51数据类型数据类型数据类型数据类型c51专用专用长度长度取值范围取值范围signed char单字节单字节-128 to +127unsigned char单字节单字节0 to 255signed int2字节字节-32768 to +32767unsigned int2字节字节0 to 65535signed long4字节字节-2147483648 to +214746483647unsigned long4字节字节0 to 4294967295float4字节字节1.175494e-38 to 3.402823e+38*13字节字节对象的地址对象的地址10数据类型数据类型c51专用专
12、用长度长度取值范围取值范围bit专用专用1位位0 或或 1sbit专用专用1位位0 或或 1sfr专用专用1字节字节0 255sfr16专用专用2字节字节0 655353.2.2 c513.2.2 c51数据类型数据类型113.2.3 3.2.3 常量及变量常量及变量v在在c51中变量定义的格式如下:中变量定义的格式如下: 存储种类存储种类 数据类型数据类型 存储器类型存储器类型 变量名表;变量名表;v变量定义中可使用的存储种类(变量定义中可使用的存储种类(storage classes)有四种:)有四种:自动(自动(auto)外部(外部(extern)静态(静态(static)寄存器(寄存器
13、(register)v变量定义时,如果省略存储种类选项,则该变量将为自动变量定义时,如果省略存储种类选项,则该变量将为自动(auto)变量()变量(默认默认)。)。12vauto类型:类型:在定义它的函数体内部有效;在定义它的函数体内部有效;进入定义它的函数体时动态分配内存,退出函数体时所占用进入定义它的函数体时动态分配内存,退出函数体时所占用的内存区域被释放(的内存区域被释放(局部变量局部变量););变量的变量的默认默认存储种类。存储种类。vregister类型:类型:作用域与寿命和作用域与寿命和auto型相同;型相同;编译器尽可能将该类变量放在编译器尽可能将该类变量放在cpu的寄存器中,以
14、提高存储的寄存器中,以提高存储速度。通常选择访问速度。通常选择访问频率较高的变量频率较高的变量定义为该类型,以提高定义为该类型,以提高效率。效率。存储种类存储种类13vextern类型类型可以在一个应用的多个程序文件中均有效;可以在一个应用的多个程序文件中均有效;存放在内存的静态存储区。直到该程序结束,分配的内存才被释放(存放在内存的静态存储区。直到该程序结束,分配的内存才被释放(全全局变量局变量)。可在函数间传递信息,在函数内被修改时,修改值会传递给其)。可在函数间传递信息,在函数内被修改时,修改值会传递给其它函数。它函数。vstatic类型类型局部变量局部变量作用域与作用域与auto类相同
15、;类相同;寿命与寿命与extern类相同。数据值在两次调用之间一直保持,占用的内存类相同。数据值在两次调用之间一直保持,占用的内存空间在程序结束才释放。空间在程序结束才释放。全局变量全局变量仅在定义它的程序文件内有效;仅在定义它的程序文件内有效;寿命与寿命与extern类相同。作用范围受限的全局变量,仅在定义它的文件类相同。作用范围受限的全局变量,仅在定义它的文件中有效。中有效。存储种类存储种类14存储区域存储区域v8051系列微处理器采用了系列微处理器采用了哈佛结构哈佛结构,即程序存储器和,即程序存储器和数据存储器是分离的。数据存储器是分离的。8051系列微处理器提供了三种不系列微处理器提供
16、了三种不同类型的存储区域(同类型的存储区域(memory areas):): 程序存储区(程序存储区(program memory)内部数据存储区(内部数据存储区(internal data memory)外部数据存储区(外部数据存储区(external data memory)v这三种存储区域均从地址这三种存储区域均从地址0开始编址,通过采用开始编址,通过采用不同不同的寻址指令的寻址指令来解决地址重叠的问题。来解决地址重叠的问题。 15存储区域的划分存储区域的划分16存储器类存储器类型型存储区域存储区域大小大小描述描述code程序存储区程序存储区64kb用来说明常量用来说明常量data直接寻
17、址的内部数据直接寻址的内部数据存储区存储区128b访问速度快访问速度快idata间接寻址的内部数据间接寻址的内部数据区区256b可访问整个内部数据区域可访问整个内部数据区域bdata位寻址的内部数据存位寻址的内部数据存储区储区16b可使用位寻址或字节寻址来可使用位寻址或字节寻址来访问这一区域访问这一区域xdata外部数据存储或外部数据存储或64kb使用使用dptr来访问外部数据来访问外部数据存储器存储器far扩充的扩充的ram和和rom使用用户定义的专用例程或使用用户定义的专用例程或特殊芯片指令扩展命令特殊芯片指令扩展命令pdata分页的外部数据存储分页的外部数据存储区区256b利用利用r0,
18、r1来访问分页的外来访问分页的外部数据存储器部数据存储器17存储器类型的变量声明举例存储器类型的变量声明举例char data var1;char code text = enter parameter:; unsigned long xdata array100; float idata x,y,z;unsigned int pdata dimension;unsigned char xdata vector1044;char bdata flags; 说明:说明:声明变量时声明变量时存储区修饰符和数存储区修饰符和数据类型修饰符的位据类型修饰符的位置可以互换,即置可以互换,即char dat
19、a x; 和和 data char x; 是完是完全等效的。不过从全等效的。不过从兼容性考虑,建议兼容性考虑,建议使用前一种格式。使用前一种格式。18存储模式(存储模式(memory models)v如果在变量声明时未声明变量的存储器类型,则该变如果在变量声明时未声明变量的存储器类型,则该变量的存储器类型,由程序的量的存储器类型,由程序的存储模式存储模式来决定。来决定。小模式(小模式(small model):默认):默认data区区紧凑模式(紧凑模式(compact model):默认):默认pdata区区大模式(大模式(large model):默认):默认xdata区区v注意:除非应用在
20、特殊的场合,否则注意:除非应用在特殊的场合,否则small存储模存储模式可以提供最快和最有效的代码。式可以提供最快和最有效的代码。 193.2.4 c513.2.4 c51中的特殊数据类型中的特殊数据类型vc51中有几种中有几种ansi c所没有的特殊数据类型,这些所没有的特殊数据类型,这些数据类型是和存储区域和存储器类型的概念密切相关的。数据类型是和存储区域和存储器类型的概念密切相关的。 位变量位变量可位寻址的对象可位寻址的对象特殊功能寄存器特殊功能寄存器20位变量位变量v位变量(位变量(bit types)是指用一个二进制位表示的变是指用一个二进制位表示的变量。位数据类型可以用来说明变量,
21、参数表,函数返回量。位数据类型可以用来说明变量,参数表,函数返回值等。位数据变量声明和基本的数据类型声明一样。值等。位数据变量声明和基本的数据类型声明一样。v所有的位变量都存储在所有的位变量都存储在内部数据区的位寻址段内部数据区的位寻址段中。因中。因为该段只有为该段只有16个字节长,所以在一个作用域内最多只个字节长,所以在一个作用域内最多只能声明能声明128个位变量。个位变量。v注意:由于位变量只能存储在内部数据存储区的位变注意:由于位变量只能存储在内部数据存储区的位变量区内,因此只能使用量区内,因此只能使用data 和和idata两种存储器类型修两种存储器类型修饰符,其它存储器类型是非法的。
22、饰符,其它存储器类型是非法的。21v例例3.15 位变量的使用位变量的使用static bit done_flag = 0; /* 位变量位变量 */bit testfunc ( /*位函数返回类型位函数返回类型 */bit flag1, /*位类型参数位类型参数 */bit flag2 )return (0); /* 位类型返回值位类型返回值 */22特殊功能寄存器特殊功能寄存器v8051系列的微控制器提供了一个独立的内存区,用来存放系列的微控制器提供了一个独立的内存区,用来存放特殊功能寄存器(特殊功能寄存器(special function register, sfr)。)。vsfr用来在
23、程序中控制定时器,计数器,串行用来在程序中控制定时器,计数器,串行i/o,端口,端口i/o操作,以及外设的操作。操作,以及外设的操作。sfr驻留在地址驻留在地址0x80到到0xff空间空间,可按可按字节寻址字节寻址或按字寻址,某些寄存器还可以按或按字寻址,某些寄存器还可以按位寻址位寻址。v8051系列微控制器中系列微控制器中sfr的个数和类型是变化的。的个数和类型是变化的。c51没没有预先定义有预先定义sfr的名字,而是提供了许多的名字,而是提供了许多8051兼容芯片的兼容芯片的包含文件包含文件,这些文件对芯片的,这些文件对芯片的sfr进行了定义。进行了定义。cx51编译编译器用器用sfr,s
24、fr16,sbit来进行来进行sfr定义。定义。23sfr:定义:定义8位特殊功能寄存器位特殊功能寄存器sfr可以用来定义可以用来定义8051单片机的单片机的8位特殊功能寄存器。位特殊功能寄存器。sfr占用一个字节内占用一个字节内存单元,取值范围是存单元,取值范围是0 255。sfr的声明和的声明和c变量的声明格式是一样的,只不过使用的修饰符不是变量的声明格式是一样的,只不过使用的修饰符不是char 或或int 而是而是sfr。例如:例如:sfr p0 = 0 x80; /* port-0, address 80h */sfr p1 = 0 x90; /* port-1, address 90
25、h */sfr p2 = 0 xa0; /* port-2, address 0a0h */sfr p3 = 0 xb0; /* port-3, address 0b0h */p0,p1,p2,p3是是sfr声明的特殊功能寄存器的名称。特殊功能寄存器声明的特殊功能寄存器的名称。特殊功能寄存器名称是一个合法的名称是一个合法的c标识符。等号后的地址必须是标识符。等号后的地址必须是数值常量数值常量,不允许使用不允许使用带运算符的表达式带运算符的表达式。24sfr16:定义:定义16位特殊功能寄存器位特殊功能寄存器8051芯片可以将两个芯片可以将两个8位位sfr作为一个作为一个16位寄存器来访问。位寄
26、存器来访问。条件是这两个条件是这两个sfr必须处在相邻地址上,并且是低字节在高必须处在相邻地址上,并且是低字节在高字节地址的前面。字节地址的前面。c51提供了提供了sfr16数据类型来进行数据类型来进行16位特殊功能寄存器的声明,位特殊功能寄存器的声明,声明时声明时低字节地址被用来作为低字节地址被用来作为sfr16的地址的地址。例如:例如:sfr16 t2 = 0 xcc; /* timer 2: t2l 0cch, t2h 0cdh */sfr16 rcap2 = 0 xca;/* rcap2l 0cah, rcap2h 0cbh */在这个例子中,在这个例子中,t2和和rcap2被声明为被
27、声明为16位的特殊功能寄存器。位的特殊功能寄存器。sfr16声明和声明和sfr声明的规则相同。声明的规则相同。25sbit:定义特殊功能位:定义特殊功能位sbit用来访问用来访问sfr中的可寻址位和其它可位寻址对象的可寻址中的可寻址位和其它可位寻址对象的可寻址位。位。在在8051应用中,经常需要对应用中,经常需要对sfr中的可寻址位(特殊功能位)中的可寻址位(特殊功能位)进行独立访问。可以用进行独立访问。可以用sbit数据类型来将数据类型来将sfr中的可寻址位声中的可寻址位声明为特殊功能位。明为特殊功能位。sbit ea = 0 xaf;上例中将上例中将ea定义为地址定义为地址0xaf,对,对
28、8051而言这是中断使能寄而言这是中断使能寄存器(存器(ie)的中断许可位。)的中断许可位。26v有三种方法来声明位地址:有三种方法来声明位地址:方法一:方法一: sfr_name int_constant,即,即sfr寄存器名寄存器名整形常整形常量。量。这种方法使用已经定义的这种方法使用已经定义的sfr作为作为sbit的基地址。该的基地址。该sfr的地址的地址必须能被必须能被8整除,整除,符号后的表达式定义了可寻址位的位地址。符号后的表达式定义了可寻址位的位地址。位地址必须是位地址必须是0-7之间的数。之间的数。sfr psw = 0 xd0;/声明寄存器名声明寄存器名sfr ie = 0
29、xa8;sbit ov = psw 2; /声明特殊功能位声明特殊功能位sbit cy = psw 7;sbit ea = ie 7;27方法二:方法二: int_constant int_constant,即整形常量,即整形常量整形整形常量。常量。这种方法使用整形常数作为基地址。该地址必须可以被这种方法使用整形常数作为基地址。该地址必须可以被8整除,整除,符号后的表达式定义了可寻址位的位地址。位地址必须是符号后的表达式定义了可寻址位的位地址。位地址必须是0-7之间的数。之间的数。sbit ov = 0 xd0 2;sbit cy = 0 xd0 7;sbit ea = 0 xa8 7;方法三
30、:方法三:int_constant用绝对位地址来声明用绝对位地址来声明sbit。sbit ov = 0 xd2;sbit cy = 0 xd7;sbit ea = 0 xaf;28v注意:注意:sbit、bit和位域是三种不同的数据类型。使用和位域是三种不同的数据类型。使用sbit声声明时,基对象必须可位寻址变量或者是可以位寻址的特殊功明时,基对象必须可位寻址变量或者是可以位寻址的特殊功能寄存器。能寄存器。类型类型访问对象访问对象sbit可位寻址变量或可位寻址的特殊功能寄存器可位寻址变量或可位寻址的特殊功能寄存器bit可位寻址区中的位,共可位寻址区中的位,共128位位位域位域将字节,整型,长整
31、型的某几个位作为一个将字节,整型,长整型的某几个位作为一个数据存储单元,进行独立访问。数据存储单元,进行独立访问。29绝对变量地址绝对变量地址v开发者有时候希望把变量存储在指定的地址单元中。可用开发者有时候希望把变量存储在指定的地址单元中。可用 _at_ 关键词来将变量定位在一个绝对的内存地址单元。关键词来将变量定位在一个绝对的内存地址单元。使用方法如下:使用方法如下:数据类型数据类型 存储器类型存储器类型 变量名变量名 _at_ 变量所在绝对地址变量所在绝对地址;v在在 _at_ 后面的绝对地址必须符合存储器类型的物理边界限后面的绝对地址必须符合存储器类型的物理边界限制,即不超过存储区域的最
32、大可寻址范围,该地址必须为常制,即不超过存储区域的最大可寻址范围,该地址必须为常数。数。30v绝对变量定位遵循以下约束:绝对变量定位遵循以下约束:绝对变量不能初始化。绝对变量不能初始化。类型为类型为bit的函数和变量不能用绝对地址定位。的函数和变量不能用绝对地址定位。绝对变量必须是全局变量,不能是局部变量。绝对变量必须是全局变量,不能是局部变量。31v例例3.18struct linkstruct link idata *next;char code *test;struct link list idata _at_ 0 x40; /* list at idata 0 x40 */char x
33、data text256 _at_ 0 xe000; /* array at xdata 0 xe000 */int xdata i1 _at_ 0 x8000; /* i1 at xdata 0 x8000 */void main ( void ) list.next = (void *) 0;i1 = 0 x1234;text 0 = a;32v有时需要在不同的模块之间调用变量,可使用下列的有时需要在不同的模块之间调用变量,可使用下列的语句来在另一个源文件中访问上例中用语句来在另一个源文件中访问上例中用 _at_修饰的变修饰的变量。量。v例例3.19struct linkstruct li
34、nk idata *next;char code *test;extern struct link idata list;/* list at idata 0 x40 */extern char xdata text256; /* array at xdata 0 xe000 */extern int xdata i1; /* int at xdata 0 x8000 */333.3.1 3.3.1 数组和指针数组和指针v数组是一个由同种类型的变量组成的集合,它保存在连续的数组是一个由同种类型的变量组成的集合,它保存在连续的存储区域中,第一个元素保存在最低地址中,最末一个元素存储区域中,第一个
35、元素保存在最低地址中,最末一个元素保存在最高地址中。保存在最高地址中。v数组可以是一维的也可以是多维的。数组可以是一维的也可以是多维的。数组的定义方式如下:数组的定义方式如下:数据类型数据类型 数组名数组名常量常量1常量常量2常量常量n;这里的这里的n是数组的维数。是数组的维数。v在定义时可以进行数组元素的初始化,初始化的值放在在定义时可以进行数组元素的初始化,初始化的值放在 中,每个元素值用逗号分开。如果是对多维数组进行初始化,中,每个元素值用逗号分开。如果是对多维数组进行初始化,还可以使用还可以使用 将元素维的大小分成组。将元素维的大小分成组。34v例如:例如:char a23=0,1,2
36、,3,4,5;char a23=0,1,2,3,4,5;v以上两条语句的功能是相同以上两条语句的功能是相同的,执行完成后各元素的值如的,执行完成后各元素的值如下:下: (设初始地址为(设初始地址为addr)地址地址对应元素对应元素 对应值对应值addra000addr+1 a011addr+2 a022addr+3 a103addr+4 a114addr+5 a12535v对于特殊的对于特殊的字符串数组字符串数组,初始化时不仅可以采用每个,初始化时不仅可以采用每个元素分别赋值,还可以以字符串的形式赋值。如元素分别赋值,还可以以字符串的形式赋值。如char array20=”hello worl
37、d”;v还可以使维数的大小为空,由初始化字串的长度决定还可以使维数的大小为空,由初始化字串的长度决定数组的长度。如数组的长度。如char array =”hello world”;上例中,数组上例中,数组array的长度为的长度为12个字节(字符串赋值时会增个字节(字符串赋值时会增加一个加一个0字符,作为字符串的字符,作为字符串的结束标志结束标志)。)。36v注意:注意:c语言中的数组元素的下标总是从语言中的数组元素的下标总是从0开始的。开始的。多维数组在内存中保存时,下标多维数组在内存中保存时,下标1变化最慢,下标变化最慢,下标n变化最快。变化最快。37指针与地址的概念指针与地址的概念v 程
38、序中的变量经过编译处理后都对应着内存中的一程序中的变量经过编译处理后都对应着内存中的一个地址。编译器根据变量的类型,为其分配不同大个地址。编译器根据变量的类型,为其分配不同大小的内存单元来存放变量的数据。小的内存单元来存放变量的数据。v 所谓所谓指针指针,就是某个变量所占用存储单元的首地址。,就是某个变量所占用存储单元的首地址。用来存放指针值的变量称为用来存放指针值的变量称为指针变量指针变量。指针变量的定义格式如下:指针变量的定义格式如下:类型说明符类型说明符 存储器类型存储器类型 *指针变量名指针变量名v 其中:其中:“*”表示定义的是指针变量,类型说明符表表示定义的是指针变量,类型说明符表
39、示该指针变量指向的变量的类型。示该指针变量指向的变量的类型。38vc51的指针和标准的指针和标准c中的指针功能相同。但是由于中的指针功能相同。但是由于8051体系结体系结构的特殊性,构的特殊性,c51提供了两种不同类型的指针:提供了两种不同类型的指针:通用指针通用指针(generic pointers)具体指针具体指针(memory-specific pointers)。)。v通用指针的声明是和标准通用指针的声明是和标准c中的指针声明是相同的,例如:中的指针声明是相同的,例如:char *s; /* 指向字符类型的指针指向字符类型的指针 */int *numptr; /* 指向整型类型的指针指
40、向整型类型的指针*/long *state;/* 指向长整型类型的指针指向长整型类型的指针 */39v通用指针总是占用三个字节通用指针总是占用三个字节。第第1个字节保存个字节保存存储器类型编码值存储器类型编码值,第第2个字节保存地址的高字节,个字节保存地址的高字节,第第3 个字节保存地址的低字节。个字节保存地址的低字节。v许多许多c51的库例程使用这种指针类型,通用指针类型的库例程使用这种指针类型,通用指针类型可以访问任何存储区域内变量。可以访问任何存储区域内变量。 存储器类型存储器类型 idata/data/bdataxdatapdatacode编码值编码值0 x000 x010 xfe0
41、xff40v具体指针具体指针是在声明时是在声明时指定了存储器类型的指针指定了存储器类型的指针,是指向特定存,是指向特定存储区域中的指针变量。储区域中的指针变量。char data *str; /* ptr to string in data */int xdata *numtab; /* ptr to int(s) in xdata */long code *powtab; /* ptr to long(s) in code */v具体指针不需要保存存储器类型字节。具体指针可以保存在一具体指针不需要保存存储器类型字节。具体指针可以保存在一个字节(个字节(idata, data, bdata,
42、pdata类型指针)或类型指针)或2个字节个字节(code 和和xdata类型指针)中。类型指针)中。v具体指针可以用来访问具体指针可以用来访问8051声明的存储区内的变量。具体指声明的存储区内的变量。具体指针的针的效率高效率高,但,但灵活性较差灵活性较差。 41体指针体指针本身的存储类型的定义本身的存储类型的定义v例:例:char data * xdata ptr; /* ptr in xdata to data char */int xdata * data numtab; /* numtab in data to xdata int */long code * idata powtab;
43、 /* powtab in idata to code long */v注意:本例中变量定义时使用了两个存储器类型,注意:本例中变量定义时使用了两个存储器类型,*前的存储器类型修饰指针指向的数据,前的存储器类型修饰指针指向的数据,*后后的存的存储器类型修饰指针本身,即储器类型修饰指针本身,即指针所占据的存储区域类型指针所占据的存储区域类型。 42v注意:完成相同的功能,使用通用指针类型的代码与注意:完成相同的功能,使用通用指针类型的代码与使用具体指针类型的代码相比,前者的运行速度要慢很使用具体指针类型的代码相比,前者的运行速度要慢很多。多。v原因:这是因为通用指针类型只有在程序运行时才能原因:
44、这是因为通用指针类型只有在程序运行时才能知道实际的变量存储区类型,因此知道实际的变量存储区类型,因此编译器就不能对内存编译器就不能对内存访问进行优化访问进行优化,从而只能生成可以访问任意存储区的通,从而只能生成可以访问任意存储区的通用代码。如果必须优先考虑程序的运行速度,那么只要用代码。如果必须优先考虑程序的运行速度,那么只要有可能就应该使用具体指针来替代通用指针有可能就应该使用具体指针来替代通用指针43指针变量的引用指针变量的引用 v在利用指针变量进行间接访问时,必须使它指向一个在利用指针变量进行间接访问时,必须使它指向一个确定的变量。确定的变量。指针变量只能存放地址指针变量只能存放地址,不
45、能将一个非地不能将一个非地址量赋给指针变量。址量赋给指针变量。vc语言中有两个与指针相关的运算符:语言中有两个与指针相关的运算符:*:指针运算符,作用是通过指针变量间接访问它所指向的变:指针运算符,作用是通过指针变量间接访问它所指向的变量,来存取数据。量,来存取数据。&:取地址运算符,作用是取得变量所占用存储单元的首地:取地址运算符,作用是取得变量所占用存储单元的首地址,即指针。址,即指针。 例子例子44v数组的指针数组的指针一个数组包含多个元素,每个数组元素都在内存中一个数组包含多个元素,每个数组元素都在内存中占用存储单元,都有相应的地址,并且这些存储单元都占用存储单元,都有相应的地
46、址,并且这些存储单元都是连续的。指针变量可以指向数组和数组的任意元素。是连续的。指针变量可以指向数组和数组的任意元素。v引用数组元素可以使用:引用数组元素可以使用:下标法(即下标法(即 运算符和对应元素的下标)运算符和对应元素的下标)指针法(即通过指向数组元素的指针找到所需元素)。指针法(即通过指向数组元素的指针找到所需元素)。45v例如:例如:float a10;float *p1,*p2;p1=a;p2=&a0;v上例运行完成后,指针上例运行完成后,指针p1和和p2的值是相同的,均指的值是相同的,均指向数组的首地址,即第一个元素。向数组的首地址,即第一个元素。注意:指向数组的指针的
47、值和指向数组首元素的指注意:指向数组的指针的值和指向数组首元素的指针的值是相同的针的值是相同的46vc语言规定,如果指针变量语言规定,如果指针变量pointer已经指向数组中的已经指向数组中的一个元素,则一个元素,则pointer+1指向同一个数组元素的下一个指向同一个数组元素的下一个元素,而不是元素,而不是pointer的值简单加的值简单加1。实际增加的大小,。实际增加的大小,由指针指向变量的类型决定。由指针指向变量的类型决定。47函数的指针函数的指针v在在c语言中,指针变量除了能指向数据对象外,也语言中,指针变量除了能指向数据对象外,也可可以指向函数以指向函数。v函数在编译时,编译器为每个
48、函数分配一个入口地址,函数在编译时,编译器为每个函数分配一个入口地址,这个这个入口地址就称为函数的指针入口地址就称为函数的指针。函数的指针可以赋给。函数的指针可以赋给函数指针变量函数指针变量,并能通过函数指针变量来调用它所指向,并能通过函数指针变量来调用它所指向的函数。的函数。指向函数指针变量的定义格式如下:指向函数指针变量的定义格式如下:类型标识符类型标识符 (*指针变量名)(参量列表)指针变量名)(参量列表)48int add(int a,int b)return a+b;int sub(int a,int b)return a-b;main()int (*pfunc)(int,int);
49、/定义函数指针变量!定义函数指针变量!int x,y;pfunc=add;/对函数指针变量赋值对函数指针变量赋值x=(*pfunc)(3,4);pfunc=sub;y=(*pfunc)(5,3);v上例运行完成后,上例运行完成后,x=7,y=2。49v说明:说明:函数指针变量定义时,函数指针变量定义时,两侧的()是必须的两侧的()是必须的,表示变量名先,表示变量名先于于*结合,是一个指针变量。然后再与后随的()结合,表示结合,是一个指针变量。然后再与后随的()结合,表示指针变量指向的对象是函数。指针变量指向的对象是函数。指向的函数的指针变量可以指向任何一个格式相同的函数的指向的函数的指针变量可
50、以指向任何一个格式相同的函数的入口地址。入口地址。c语言约定,函数名本身就是函数的入口地址。语言约定,函数名本身就是函数的入口地址。当函数指针变量指向函数时,即可用它来调用所指的函数。当函数指针变量指向函数时,即可用它来调用所指的函数。调用格式为(调用格式为(*指针变量名)(实参表)指针变量名)(实参表)503.8 3.8 函数函数v在在c语言中,语言中,函数函数是程序的基本组成单位是程序的基本组成单位。函数不仅。函数不仅可以实现程序的可以实现程序的模块化模块化,提高程序的,提高程序的可读性可读性和和可维护性可维护性,使程序设计变得简单和直观,还可以把程序中经常用到使程序设计变得简单和直观,还
51、可以把程序中经常用到的一些计算或操作设计成通用的函数,以供随时调用。的一些计算或操作设计成通用的函数,以供随时调用。vc程序由程序由一个主函数一个主函数main()和和若干个其它函数若干个其它函数组成。组成。由主函数调用其它函数,其它函数也可以互相调用,同由主函数调用其它函数,其它函数也可以互相调用,同一个函数可以被调用多次。一个函数可以被调用多次。51v函数定义函数定义函数定义的一般形式函数定义的一般形式是:是:函数类型函数类型 函数名函数名(形式参数列表形式参数列表)局部变量声明部分局部变量声明部分语句(有返回值的要有语句(有返回值的要有return语句)语句)v函数类型定义了函数中返回语
52、句(函数类型定义了函数中返回语句(return)返回值的)返回值的数据类型,返回值可以是任何一种有效的数据类型。如数据类型,返回值可以是任何一种有效的数据类型。如果没有使用函数类型说明符,函数返回值默认为整形值。果没有使用函数类型说明符,函数返回值默认为整形值。52v参数表是一个用逗号分隔的变量表,当函数被调用时参数表是一个用逗号分隔的变量表,当函数被调用时这些变量接收调用参数的值。一个函数可以没有参数,这些变量接收调用参数的值。一个函数可以没有参数,这时函数参数表是空的。这时函数参数表是空的。注意即使没有参数,括号仍是注意即使没有参数,括号仍是必须的。必须的。vc51对函数的功能进行了扩展,
53、函数对函数的功能进行了扩展,函数定义的完整形式定义的完整形式如下:如下:函数类型函数类型 函数名函数名(形式参数列表形式参数列表) small | compact | large reentrant interrupt m using n 53v函数返回值函数返回值返回语句返回语句return用来回送一个数值给定义的函数,完成后从用来回送一个数值给定义的函数,完成后从函数中退出。如果函数没有返回值可以不使用函数中退出。如果函数没有返回值可以不使用return语句,语句,或使用不带返回值的或使用不带返回值的return语句。语句。v关于返回值有以下几条注意点:关于返回值有以下几条注意点:返回值是
54、通过返回值是通过return语句返回的。语句返回的。返回值的类型如果与函数定义的类型不一致,那么返回值将返回值的类型如果与函数定义的类型不一致,那么返回值将被自动转化为函数定义的类型。被自动转化为函数定义的类型。如果没有如果没有return语句,函数会返回一个不确定的值。因此如语句,函数会返回一个不确定的值。因此如果函数无需返回值,可以用果函数无需返回值,可以用”void”类型说明符指明函数无返类型说明符指明函数无返回值。回值。54形式参数与实际参数形式参数与实际参数v与使用变量一样,在调用一个函数之前,必须对该函数进行声与使用变量一样,在调用一个函数之前,必须对该函数进行声明,即明,即先声明
55、后调用先声明后调用。函数声明的一般形式是:函数声明的一般形式是:函数类型函数类型 函数名(形式参数列表);函数名(形式参数列表);v函数定义时参数列表中的参数称为函数定义时参数列表中的参数称为形式参数形式参数,简称形参,简称形参,它们它们同函数内部的局部变量作用相同同函数内部的局部变量作用相同,形参的定义是在函数名后的括形参的定义是在函数名后的括号中。号中。v函数调用时所使用的替换参数,是函数调用时所使用的替换参数,是实际参数实际参数,简称实参。定义,简称实参。定义的形参与调用函数的实参类型应该一致,书写顺序应该相同。的形参与调用函数的实参类型应该一致,书写顺序应该相同。使用函数的注意事项:使
56、用函数的注意事项:1、函数定义时要同时声明其类型。、函数定义时要同时声明其类型。2、调用函数前要先声明该函数。、调用函数前要先声明该函数。3、传给函数的参数值,其类型要与函数原定义一致。、传给函数的参数值,其类型要与函数原定义一致。4、接受函数返回值的变量,其类型也要与函数一致。、接受函数返回值的变量,其类型也要与函数一致。55v在在c语言中对不同类型的实际参数,有三种不同的语言中对不同类型的实际参数,有三种不同的参数传递方参数传递方式式:v基本数据类型的参数传递基本数据类型的参数传递当函数的参数是一般类型变量时,主调函数将实际参数的值传递给被调当函数的参数是一般类型变量时,主调函数将实际参数
57、的值传递给被调用函数中的形式参数,这种方式称为用函数中的形式参数,这种方式称为传值调用传值调用。这种参数传递方式下形式。这种参数传递方式下形式参数的值发生改变时,实际参数的值不会受到影响。因此值传递是一种单参数的值发生改变时,实际参数的值不会受到影响。因此值传递是一种单向传递。向传递。v数组类型的参数传递数组类型的参数传递当函数的参数是数组类型的变量时,主调函数将实际参数数组的起始地当函数的参数是数组类型的变量时,主调函数将实际参数数组的起始地址传递到被调用函数中的形式参数中,这种方式称为址传递到被调用函数中的形式参数中,这种方式称为地址传递地址传递。这种参数。这种参数传递方式下形式参数的值发
58、生改变时,实际参数的值也会改变,因此地址传递方式下形式参数的值发生改变时,实际参数的值也会改变,因此地址传递是一种双向传递。传递是一种双向传递。v指针类型的参数传递指针类型的参数传递当函数的参数是指针类型的变量时,主调函数将实际参数的地址传递给当函数的参数是指针类型的变量时,主调函数将实际参数的地址传递给被调用函数的形式参数,因此也是被调用函数的形式参数,因此也是地址传递地址传递。这种参数传递方式下形式参。这种参数传递方式下形式参数的值发生改变时,实际参数的值也会改变。数的值发生改变时,实际参数的值也会改变。56函数调用方式函数调用方式v函数调用格式:函数名(实参列表)v在一个函数中调用另一函
59、数需要具备下面的条件。在一个函数中调用另一函数需要具备下面的条件。被调用的函数必须是已经存在的函数,即已经声明或定义的被调用的函数必须是已经存在的函数,即已经声明或定义的函数。(库函数或自定义函数)函数。(库函数或自定义函数)如果是库函数,应该在程序开头用如果是库函数,应该在程序开头用#include命令将有关库函命令将有关库函数所需用到的信息包含到本程序中来。数所需用到的信息包含到本程序中来。如果是用户定义的函数,一般还应该对被调用的函数做如果是用户定义的函数,一般还应该对被调用的函数做函数函数声明声明。57v自定义函数的声明:自定义函数的声明: 函数原型格式为:函数原型格式为: exter
60、n 函数类型函数类型 函数名(形式参数列表);函数名(形式参数列表); 函数的声明是指明:函数的名字、类型以及形参的类函数的声明是指明:函数的名字、类型以及形参的类型、个数和顺序型、个数和顺序vp45例例3-26、3-27v函数的调用方式,如下:函数的调用方式,如下:函数调用方式函数调用方式58函数的调用方式:函数的调用方式:v调用函数的方式可以是以下几种:调用函数的方式可以是以下几种:函数作为语句函数作为语句:把函数调用作为一个语句,不使用函数返回:把函数调用作为一个语句,不使用函数返回值,只是完成函数所定义的操作。值,只是完成函数所定义的操作。函数作为表达式函数作为表达式:函数调用出现在一个表达式中,使用函数:函数调用
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 外贸英语写作课件百度云
- 探秘电流世界
- 硕士追求指南
- 四川省成都市第第十八中学2025届初三下学业水平考试生物试题试卷含解析
- 天津美术学院《现代推销学实验》2023-2024学年第一学期期末试卷
- 山西省左玉县市级名校2024-2025学年初三下学期期末教学质量检查数学试题含解析
- 南宁二中、柳州高中2024-2025学年高三下学期第9周周考物理试题含解析
- 山西传媒学院《现代生物制药工程原理》2023-2024学年第二学期期末试卷
- 上海外国语大学《文化与翻译(1)》2023-2024学年第一学期期末试卷
- 山东省乐陵市第一中学重点名校2025年初三下学期物理试题周练二不含附加题含解析
- GB/T 38192-2019注射成型塑料圆柱齿轮精度制轮齿同侧齿面偏差和径向综合偏差的定义和允许值
- 外科学试题库及答案(共1000题)
- 建筑机械使用安全技术规程 jgj33-2012
- 版-3-反应器设计说明书
- 安徽省水环境功能区划
- 外科学总论教案-麻醉
- 《数据结构》课件(完整版)
- 事业单位干部自传和干部履历表范文
- D502-15D502等电位联结安装图集
- 牛排西式餐厅管理餐饮培训资料 豪客来 服务组排班表P1
- 一文看懂友宝在线招股书
评论
0/150
提交评论