指针C51.

合集下载

第3章 C51的指针

第3章 C51的指针

C51的指针指针是C语言的一个特殊的变量,它存储的数值被解释成为内存的一个地址。

指针定义的一般形式如下。

数据类型*指针变量名;例如:int i,j,k,*i_ptr; //定义整型变量i,j,k和整型指针变量i_ptr。

指针运算包括以下两种:(1)取地址运算符。

取地址运算符&是单目运算符,其功能是取变量的地址,例如:i_ptr=&i; //变量i的地址送给指针变量i_ptr(2)取内容运算符。

取内容运算符“*”是单目运算符,用来表示指针变量所指单元的内容,在星号“*”运算符之后跟的必须是指针变量。

例如:j=*i_ptr; //将i_ptr所指的单元的内容赋给变量j可以把数组的首地址赋予指向数组的指针变量。

例如:int a[5],*ap;ap=a; //数组名表示数组的首地址,故可赋予指向数组的指针变量也可以写成:ap=&a[0]; //数组第一个元素的地址也是整个数组的首地址,也可赋予指针变量ap 还可以采用初始化赋值的方法:int a[5],*ap=a;也可以把字符串的首地址赋予指向字符类型的指针变量。

例如:unsigned char *cp;cp="Hello World!";这里应该说明的是,并不是把整个字符串装入指针变量,而是把存放该字符串的字符数组的首地址装入指针变量。

对于指向数组的指针变量,可以进行加减运算,例如:cp--; //cp指向上一个数组元素ap++; //ap指向下一个数组元素例如:定义了指针类型的形式参数如下:uchar *str;该形式参数表示一个无符号字符型变量的地址。

可以采用以下赋值语句:SBUF=*(str+k); //将单元地址为str+k的内容赋给专用寄存器SBUF,启动发送在调用该函数时,直接把数组trdata[]的数组名作为实际参数代入即可,因为数组名表示数组的首地址,故可直接赋予指向数组的指针变量。

c51指针用法

c51指针用法

c51指针用法
C51是一种常用的单片机,使用指针可以更灵活地操作内存和外设。

在C51中,指针可以用于访问和操作内存中的数据,也可以用于操作外设寄存器。

首先,我们可以使用指针来访问和操作内存中的数据。

在C51中,内存被分为不同的存储区域,如代码区、数据区和堆栈区。

通过使用指针,我们可以直接访问和修改这些存储区域中的数据。

例如,我们可以使用指针来读取和修改数组中的元素,而不需要使用数组索引。

这种方法可以提高程序的执行效率。

其次,指针还可以用于操作外设寄存器。

在单片机编程中,外设寄存器用于控制和配置外部设备,如GPIO(通用输入输出)、定时器和串口等。

通过使用指针,我们可以直接访问和修改这些寄存器的值,从而控制外部设备的行为。

例如,我们可以使用指针来设置GPIO引脚的状态,或者配置定时器的工作模式。

除了访问和操作内存和外设寄存器,指针还可以用于动态内存分配和数据结构的操作。

在C51中,我们可以使用指针来动态分配内存,并在运行时根据需要分配和释放内存。

这种灵活的内存管理方式可以提高程序的效率和灵活性。

此外,指针还可以用于创建和操作复杂的数据结构,如链表和树等。

通过使用指针,我们可以方便地插入、删除
和修改数据结构中的元素。

总之,C51中的指针用法非常重要,可以帮助我们更灵活地操作内存和外设。

通过使用指针,我们可以提高程序的执行效率,实现动态内存分配,以及创建和操作复杂的数据结构。

因此,熟练掌握C51指针的用法对于单片机编程非常重要。

C51 指针问题

C51 指针问题

C51 指针问题一般指针一般指针的声明和使用均与标准C 相同,不过同时还可以说明指针的存储类型,例如:long * state;为一个指向long 型整数的指针,而state 本身则依存储模式存放。

char * xdata ptr;ptr 为一个指向char 数据的指针,而ptr本身放于外部RAM 区,以上的long,char 等指针指向的数据可存放于任何存储器中。

一般指针本身用3 个字节存放,分别为存储器类型,高位偏移,低位偏移量。

2.存储器指针基于存储器的指针说明时即指定了存贮类型,例如:chardata * str;str 指向data 区中char 型数据int xdata * pow; pow 指向外部RAM 的int 型整数。

这种指针存放时,只需一个字节或2 个字节就够了,因为只需存放偏移量。

/*.........................................................................................char * xdata ptr;//ptr 本身放在Xdata(XRAM)区char xdata * ptr;//ptr 指向的数据放在Xdata(XRAM)区........................................................................................*/char xdata * pxchar xdata * data pxdata char xdata * px 这3 者有什么不同??char xdata * pxpx 本身存在于自动分配的空间,一般位于data 中,指向的内容位于xdatachar xdata * data pxpx 本身存在于data 空间,指向的内容位于xdatadata char xdata * px =char xdata *data pxdata:固定指前面0x00-0x7f 的128 个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。

C51的数据类型

C51的数据类型

C51的数据类型引言概述:C51是一种常用的单片机型号,它具有丰富的数据类型,这些数据类型在嵌入式系统中具有重要的作用。

本文将详细介绍C51的数据类型,包括基本数据类型、指针类型、数组类型、结构体类型以及枚举类型。

一、基本数据类型1.1 位类型(bit):C51提供了位类型,用于表示一个二进制位的数据。

位类型可以用于节省内存空间,特别适用于对一个变量的各个位进行操作的场景。

1.2 字符类型(char):C51的字符类型用于表示一个字符的数据,它占用一个字节的内存空间。

字符类型可以用于表示ASCII码字符,也可以用于表示整数。

1.3 整数类型(int):C51的整数类型用于表示整数数据。

根据不同的编译器和硬件平台,整数类型的长度可以不同,一般为2个字节或4个字节。

二、指针类型2.1 指针类型(*):C51的指针类型用于表示一个变量的地址。

通过指针类型,可以实现对变量的间接访问,提高程序的灵活性和效率。

2.2 空指针(NULL):C51提供了空指针常量NULL,用于表示一个无效的指针。

空指针在程序中常用于初始化指针变量或判断指针是否有效。

2.3 指针运算:C51支持指针的运算,包括指针的加法、减法和比较运算。

指针运算可以用于实现数组的访问和遍历。

三、数组类型3.1 一维数组:C51的一维数组用于存储相同类型的数据,可以通过下标访问数组元素。

一维数组在嵌入式系统中广泛应用,用于存储大量的数据。

3.2 多维数组:C51的多维数组是一种特殊的一维数组,它可以存储多维的数据。

多维数组可以用于表示矩阵、图像等复杂的数据结构。

3.3 字符串数组:C51的字符串数组是一种特殊的字符数组,用于存储字符串数据。

字符串数组在嵌入式系统中常用于存储文本信息。

四、结构体类型4.1 结构体定义:C51的结构体类型用于表示一组相关的数据,可以包含不同类型的成员变量。

通过结构体类型,可以方便地组织和操作复杂的数据结构。

4.2 结构体成员访问:C51使用点操作符(.)来访问结构体的成员变量。

C51的数据类型

C51的数据类型

C51的数据类型C51是一种常用的单片机型号,广泛应用于嵌入式系统和微控制器开发中。

在C51编程中,数据类型是非常重要的概念,它决定了变量在内存中的存储方式和所占用的空间大小。

本文将详细介绍C51的数据类型及其特点。

一、基本数据类型1. 位(bit):C51的最小存储单位是位,它只能存储0或1。

位类型的变量在内存中占用1位空间。

2. 位域(bit-field):位域是一种特殊的数据类型,它允许将一个字节中的位划分为多个字段,并为每个字段指定不同的位数。

位域可以节省内存空间,提高程序的执行效率。

3. 字节(byte):字节是C51中最基本的数据类型,它占用8位空间,可以存储-128到127之间的整数。

4. 无符号字节(unsigned byte):无符号字节是字节的一种特殊类型,它只能存储0到255之间的整数。

5. 半字(halfword):半字是由两个字节组成的数据类型,它占用16位空间,可以存储-32768到32767之间的整数。

6. 无符号半字(unsigned halfword):无符号半字是半字的一种特殊类型,它只能存储0到65535之间的整数。

7. 字(word):字是由四个字节组成的数据类型,它占用32位空间,可以存储-2147483648到2147483647之间的整数。

8. 无符号字(unsigned word):无符号字是字的一种特殊类型,它只能存储0到4294967295之间的整数。

二、扩展数据类型1. 长整型(long):长整型是C51中的扩展数据类型,它占用4个字节空间,可以存储更大范围的整数,从-2147483648到2147483647之间。

2. 无符号长整型(unsigned long):无符号长整型是长整型的一种特殊类型,它只能存储0到4294967295之间的整数。

3. 单精度浮点型(float):单精度浮点型是一种用于表示带小数部分的数值的数据类型,它占用4个字节空间,可以存储小数。

C51的数据类型

C51的数据类型

C51的数据类型引言概述:C51是一种常用的微控制器,广泛应用于嵌入式系统中。

在C51编程中,了解和正确使用数据类型是非常重要的。

本文将详细介绍C51的数据类型,包括基本数据类型、派生数据类型、数组和指针、结构体和联合体、枚举类型。

一、基本数据类型:1.1 位类型(bit):C51中最小的数据类型,只能存储0或1,用于表示开关状态等。

1.2 字符类型(char):用于存储一个字符,占用一个字节的内存空间,范围为-128到127。

1.3 整数类型(int):用于存储整数值,占用两个字节的内存空间,范围为-32768到32767。

二、派生数据类型:2.1 无符号整数类型(unsigned):用于存储非负整数值,范围为0到65535。

2.2 短整数类型(short):用于存储较小的整数值,占用一个字节的内存空间,范围为-128到127。

2.3 长整数类型(long):用于存储较大的整数值,占用四个字节的内存空间,范围为-2147483648到2147483647。

三、数组和指针:3.1 数组:C51中的数组是一种存储相同类型数据的集合,可以按照索引访问其中的元素。

数组的大小在声明时确定,可以是一维或多维的。

3.2 指针:指针是一种特殊的数据类型,用于存储内存地址。

在C51中,指针可以指向任何类型的数据。

通过指针,可以实现对内存中数据的直接访问和操作。

四、结构体和联合体:4.1 结构体:结构体是一种自定义的数据类型,可以将不同类型的数据组合在一起,形成一个新的数据类型。

结构体的成员可以是基本数据类型或其他结构体。

4.2 联合体:联合体是一种特殊的结构体,所有成员共享同一块内存空间。

联合体的大小取决于最大成员的大小,只能同时存储一个成员的值。

五、枚举类型:5.1 枚举类型:枚举类型用于定义一组命名的常量,可以提高程序的可读性。

在C51中,枚举类型的取值范围为整数类型。

总结:C51的数据类型包括基本数据类型(位类型、字符类型、整数类型)、派生数据类型(无符号整数类型、短整数类型、长整数类型)、数组和指针、结构体和联合体、枚举类型。

keil c51函数指针

keil c51函数指针

Keil C51 中的函数指针和再入函数,函数指针与overlay=====调用树的保存C51不把函数参数压栈(除非使用再入函数)。

函数参数和全局变量被存入寄存器或固定的存储空间。

这样阻止函数的再入。

例如,一个函数调用它自己,它将覆盖它自己的参数或存储空间。

函数的再入问题通过关键字“reentrant”来解决。

函数指针的非再入函数的副作用,在执行中出现问题。

MAIN函数调用FUNC和FUNC_CALLER(根据调用树)。

用函数的指针来传递参数,调用树往往会出错。

=====转这篇文章是由Keil C51 的英文文档翻译过来的,很多语句都是根据自己的理解翻译的,肯定还有许多地方需要推敲。

希望读者能吸取到有用的部分,不要被误解了,自己多理解。

Overlay修改用于数据覆盖的调用树。

如果在用户程序里使用了函数指针,或者使用了像实时操作系统中调度器那样的跳转(k 指的是指针方式的调用吗?),那么,修改程序调用树将是很有必要的。

混合编程:函数名符号名解释viod func(void) FUNC 无参数传递,或不含寄存器参数的函数名不作改变转入目标文件中,名字只是简单地转为大写形式viod func(char) _FUNC 带寄存器参数的函数名加入“_”字符前缀,它表明这类函数包含寄存器内的参数传递viod func(viod) reentrant _?FUNC “_?”表示可重入,它表明该行数包含栈内的参数传递。

====将下面这篇的难点内容提到前面使用函数指针的附加说明如果你在C51中使用函数指针编程,有几个附加的说明你必须注意。

参数列表的限制通过函数指针传递参数给函数必须把所有的参数存入寄存器。

在大部分情况下,3个参数能够自动通过寄存器传递。

在C51的用户手册中能找到传递参数进入寄存器的运算法则。

但是并不保证,任何的3个数据类型可以传递。

因为C51在寄存器中传递3个参数,用于传递参数的存储空间是不被分配的,除非函数指向一个要求更多参数的函数。

C51的指针类型

C51的指针类型
int *address; address=100; 这种赋值是不合法的。指针变量正确的使用方法如下: int i; int *address; 定义一个整型变量i,还定义了一个指向整型数的指针变量 address。i中可存放整数,而address中只能存放整型变量的地 址。可以把i的地址赋给address。 address=&i; 此时指针变量address指向整型变量i。
1.3 指针与数组
指针和数组有着密切的关系,任何能出数组下标完成的操作也 都可用指针来实现,但程序中使用指针可使代码更紧凑、更灵活。
采用指针访问数组元素的地址和内容有以下几种表示形式:
1
2
3
(1) p+i和a+i均表 示a[i]的地址,或者 说它们均指向数组第 i号元素,即指向 a[i]。
(2) *(p+i)和*(a+i)都 表示p+i和a+i所指对象 的内容,即为a[i]。
C51的指针类型
C51的指针类型
指针、地址、数组及其相互关系是C语言中最有特 色的部分。规范地使用指针,可以使程序达到简单明 了。因此,不但要学会如何正确地使用指针,还要学 会在各种情况下正确地使用指针变量。
1.1 指针变量的定义
变量在计算机内是占有一块存贮区域的,变量的值就存放在这块区 域之中.在计算机内部,通过访问或修改这块区域的内容来访问或修改 相应的变量。在C语言中,对于变量的访问形式之一,就是先找到变量 的地址,然后再通过该地址对变量进行访问,这就是指针及其指针变量。 所谓变量的指针,实际上是指变量的地址。变量的地址在形式上好像是 一个整数,表示变量所在的地址,它属于一种新的数据类型,即指针类 型。
(3)指向数组元素 的指针,也可以表示 成数组的形式,如 p[i]与*(p+i)等价。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C51编译器-语言扩展(3)-指针Pointers指针Cx51支持使用字符*来声时一个指针类型的变量。

Cx51的指针可以完成标准C的所有功能。

然而,由于8051及其变种的特殊构架,Cx51使用两种类的指针: memory-specific pointers and generic pointers(特定存储器类型指针和通用指针),Generic Pointers通用指针的定义方法与标准C指针的定义方法相同。

通用指针总是使用三个字节来存储。

第一个字节是存储器类型。

第二字节是偏移量的高位,第三字节是偏移量的低位。

通用指针可以访问所用的变量,而不论变量位于8051的哪一个存储区内。

因为这个原因,许多8051的运行时库都使用这个种指针。

通过使用通用指针,函数可以访问所有的内存区域注意:使用通用指针产生的代码比用特定存储器类型指针生成的代码执效率要低得多。

这是因为在运行前变量的内存区域是不知道的。

编译器不能优化存储器的访问,而是要生成适合所有存域的代码。

如果要获得高的运行速度,最好使用特定存储器类型指针。

为运行速度考虑,也可以设定指针的存储区,在声明指针时前面加上储存区类型标识就可以把指针放在特定的存储器区域。

char * xdata strptr; /* generic ptr stored in xdata */int * data numptr; /* generic ptr stored in data */long * idata varptr; /* generic ptr stored in idata */在上面的例子中,指针指向的内容可以放在任何一个空间内,但指针必须放在xdata, data, and idata中。

Memory-specific Pointers特定存储器类型指针在声明时总是包含了内存类型的声明,并且只能指向特定的内存区域。

如: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 */因为在编译的时候内存的类型就已经确定了,通用指针的存储器类型就不再需要了。

指针可以放在一个字节(idata, data, bdata, pdata)或两个字节(code, xdata)中。

根通用针一样,我们可以指特定存储器类型指针的存储区域,如char data * xdata str; /* ptr in xdata to data char */int xdata * data numtab; /* ptr in data to xdata int */long code * idata powtab; /* ptr in idata to code long */在上面的例子中,指针指向的内容可以放在任何一个空间内,但指针必须放在xdata, data, and idata中Pointer Conversions指针变换Cx51可以使通用指针和特定存储类型指针相互转换,这种转换可以通过程序代码声时转换,也可以由编译器强迫执行。

当一个特定存储器类型指针的参数传给一个便用指针做参数的函数,Cx51编译器就进行指针类型的转换。

当一个特定存储器类型指针传给一个函数,而这个函的原型又没有出现时总是转换成通用指针。

而如果这个函数使用的是短指针,这时就会发生错误。

为了避免在程序中出现这种错误,使#include文件,并声明所有外部函数的原型。

转换细节generic * to code * The offset section (2 bytes) of the generic pointer is used.generic * to xdata * The offset section (2 bytes) of the generic pointer is used.generic * to data * The low-order byte of the generic pointer offset is used.The high-order byte is discarded.generic * to idata * The low-order byte of the generic pointer offset is used.The high-order byte is discarded.generic * to pdata * The low-order byte of the generic pointer offset is used.The high-order byte is discarded.转换细节xdata * to generic * The memory type of the generic pointer is set to 0x01 for xdata.The 2-byte offset of the xdata * is used.code * to generic * The memory type of the generic pointer is set to 0xFF for code.The 2-byte offset of the code * is used.idata * to generic * The memory type of the generic pointer is set to 0x00 for idata / data.data * to generic * The 1-byte offset of the idata * / data * is converted to an unsigned int and used as the offset.pdata * to generic * The memory type of the generic pointer is set to 0xFE for pdata.The 1-byte offset of the pdata * is converted to an unsigned int and used as the offset.Abstract Pointers抽象指针抽象指针可以访问位于任何存储区域的固定的存储器。

也可以使用抽象指针调用位于固定位置或结对地址的函数。

固定指针举例:先定义变量:char xdata *px; /* ptr to xdata */char idata *pi; /* ptr to idata */char code *pc; /* ptr to code */char c; /* char variable in data space */int i; /* int variable in data space */以下例子把main C函数的地址赋给一个指向code空间的char类型的指针(存储在数据区)Source: pc=(void *)main;Object: 0000 750000 R MOV pc,#HIGH main0003 750000 R MOV pc+01H,#LOW main以下代码把变量i的地址赋给指向idata区的char类型的指针Source: pi=(char idata *) &i;Object: 0000 750000 R MOV pi,#LOW i以下代码把一个指向xdata区域的char类型的指针赋给一个指向idata区域的char类型的指针。

由于前者占用两个字节而后都占用一个字节,所以在赋值的时候只把低位字节进行了赋值,所以达不到想要的效果Source : pi = (char idata *) px;Object : 0000 850000 R MOV pi,px+01H以下例子把0x1234做为一个指针赋给一个指向code区的char类型的指针:Source:pc = (char code *) 0x1234;Object : 0000 750012 R MOV pc,#012H0003 750034 R MOV pc+01H,#034H以下例子把0xff00转换成了一个没有参数且返回值为int类型的函数指针,调用这个函数,并且把返回值赋给变量i。

通过在函数指针后面的参数列表里添加参数,编译器会正确地调用这个函数。

Source:i = ((int (code *)(void)) 0xFF00) ();Object: 0000 12FF00 LCALL 0FF00H0003 8E00 R MOV i,R60005 8F00 R MOV i+01H,R7以下代码把0x8000转换成一个指向code存储区的char类型的指针,并把这个指针指向的内容赋给变量c。

Source: c = *((char code *) 0x8000);Object : 0000 908000 MOV DPTR,#08000H0003 E4 CLR A0004 93 MOVC A,@A+DPTR0005 F500 R MOV c,A以下代码把0xff00转换成一个指向xdata区的确良char类型的指针,并把指针指向的内容加上变量c,再赋给变量cSource : c += *((char xdata *) 0xFF00);Object : 0000 90FF00 MOV DPTR,#0FF00H0003 E0 MOVX A,@DPTR0004 2500 R ADD A,c0006 F500 R MOV c,A以下代码把0xf0转换成一个指向idata区域的char类型的指针,并把指针指向的内容加上变量c再赋给变量cSource : c += *((char idata *) 0xF0);Object : 0000 78F0 MOV R0,#0F0H0002 E6 MOV A,@R00003 2500 R ADD A,c0005 F500 R MOV c,A以下代码把经0xe8转换成一个指向pdata区char类型的指针,并把指针指向的内加到变量上cSource : c += *((char pdata *) 0xE8);Object : 0000 78E8 MOV R0,#0E8H0002 E2 MOVX A,@R00003 2500 R ADD A,c0005 F500 R MOV c,A以下代码把0x2100转换成一个指向code区int类型的指针,并把指针指向的内容赋给变量iSource : i = *((int code *) 0x2100);Object : 0000 902100 MOV DPTR,#02100H0003 E4 CLR A0004 93 MOVC A,@A+DPTR0005 FE MOV R6,A0006 7401 MOV A,#01H0008 93 MOVC A,@A+DPTR0009 8E00 R MOV i,R6000B F500 R MOV i+01H,A以下代码把0x4000转换成一个指针,这个指针指向一个指针,这个被指向的指针位于xdata区域并指向xdata区域的char类型,把这个被指向的指针赋给pxSource : px = *((char xdata * xdata *) 0x4000);Object : 0000 904000 MOV DPTR,#04000H0003 E0 MOVX A,@DPTR0004 FE MOV R6,A0005 A3 INC DPTR0006 E0 MOVX A,@DPTR0007 8E00 R MOV px,R60009 F500 R MOV px+01H,A上面的例子相同,以下代码把0x4000转换成一个指向指针的指针,被指向的指针位于xdata区并指向xdata区char类型。

相关文档
最新文档