指针类型和存储区的关系详解
C中data,idata,xdata,pdata的区别
data: 固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。
idata: 固定指前面0x00-0xff的256个RAM,其中前128和data的128完全相同,只是因为访问的方式不同。
idata是用类似C中的指针方式访问的。
汇编中的语句为:mox ACC,@Rx.(不重要的补充:c中idata做指针式的访问效果很好)xdata: 外部扩展RAM,一般指外部0x0000-0xffff空间,用DPTR访问。
pdata: 外部扩展RAM的低256个字节,地址出现在A0-A7的上时读写,用movx ACC,@Rx读写。
这个比较特殊,而且C51好象有对此BUG, 建议少用。
但也有他的优点,具体用法属于中级问题,这里不提。
startup.a51的作用,和汇编一样,在C中定义的那些变量和数组的初始化就在startup.a51中进行,如果你在定义全局变量时带有数值,如unsigned char data xxx="100";,那startup.a51中就会有相关的赋值。
如果没有=100,startup.a51就会把他清0。
(startup.a51==变量的初始化)。
这些初始化完毕后,还会设置SP指针。
对非变量区域,如堆栈区,将不会有赋值或清零动作。
有人喜欢改startup.a51,为了满足自己一些想当然的爱好,这是不必要的,有可能错误的。
比如掉电保护的时候想保存一些变量, 但改startup.a51来实现是很笨的方法,实际只要利用非变量区域的特性,定义一个指针变量指向堆栈低部:0xff处就可实现。
, 为什么还要去改? 可以这么说:任何时候都可以不需要改startup.a51,如果你明白它的特性。
bit是在内部数据存储空间中 20H .. 2FH 区域中一个位的地址,这在DatA的20H以后以字节形式出现,可互相参照。
另外加上8051 可寻址的SFR,但刚刚试过,只是00H--7FH起作用,也就是说当数据有变化时颜色变红,以后的从80H到--FFH就不是位寻址区了,是位寻址的特殊寄存器,如涉及到了可位寻址的那11个当然会有反应。
C51中data,idata,xdata 区别
dATa: 固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。
idATa: 固定指前面0x00-0xff的256个RAM,其中前128和dATa的128完全相同,只是因为访问的方式不同。
idA Ta是用类似C中的指针方式访问的。
汇编中的语句为:mox ACC,@Rx.(不重要的补充:c中idATa做指针式的访问效果很好)xdA Ta: 外部扩展RAM,一般指外部0x0000-0xffff空间,用DPTR访问。
pdA Ta: 外部扩展RAM的低256个字节,地址出现在A0-A7的上时读写,用movx ACC,@Rx 读写。
这个比较特殊,而且C51好象有对此BUG, 建议少用。
但也有他的优点,具体用法属于中级问题,这里不提。
startup.a51的作用,和汇编一样,在C中定义的那些变量和数组的初始化就在startup.a51中进行,如果你在定义全局变量时带有数值,如unsigned char dATa xxx="100";,那startup.a51中就会有相关的赋值。
如果没有=100,startup.a51就会把他清0。
(startup.a51==变量的初始化)。
这些初始化完毕后,还会设置SP指针。
对非变量区域,如堆栈区,将不会有赋值或清零动作。
有人喜欢改startup.a51,为了满足自己一些想当然的爱好,这是不必要的,有可能错误的。
比如掉电保护的时候想保存一些变量, 但改startup.a51来实现是很笨的方法,实际只要利用非变量区域的特性,定义一个指针变量指向堆栈低部:0xff处就可实现。
, 为什么还要去改? 可以这么说:任何时候都可以不需要改startup.a51,如果你明白它的特性。
bit是在内部数据存储空间中20H .. 2FH 区域中一个位的地址,这在DATA的20H以后以字节形式出现,可互相参照。
另外加上8051 可寻址的SFR,但刚刚试过,只是00H--7FH起作用,也就是说当数据有变化时颜色变红,以后的从80H到--FFH就不是位寻址区了,是位寻址的特殊寄存器,如涉及到了可位寻址的那11个当然会有反应。
单片机中关键字data,idata,xdata,pdata,bdata
写在最前面的话:官方网站的解答是最可信的。
英语不错的必看。
/support/man/docs/c51/c51_le_memtypes.htm下面转载几篇中文的,仅供参考。
data:固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。
idata:固定指前面0x00-0xff的256个RAM,其中前128和data的128完全相同,只是因为访问的方式不同。
idata是用类似C中的指针方式访问的。
汇编中的语句为:mox ACC,@Rx.(不重要的补充:c中idata做指针式的访问效果很好)xdata:外部扩展RAM,一般指外部0x0000-0xffff空间,用DPTR访问。
pdata:外部扩展RAM的低256个字节,地址出现在A0-A7的上时读写,用movx ACC,@Rx读写。
这个比较特殊,而且C51好象有对此BUG, 建议少用。
但也有他的优点,具体用法属于中级问题,这里不提。
startup.a51的作用和汇编一样,在C中定义的那些变量和数组的初始化就在startup.a51中进行,如果你在定义全局变量时带有数值,如unsigned char data xxx="100";,那startup.a51中就会有相关的赋值。
如果没有=100,startup.a51就会把他清0。
(startup.a51 ==变量的初始化)。
这些初始化完毕后,还会设置SP指针。
对非变量区域,如堆栈区,将不会有赋值或清零动作。
有人喜欢改startup.a51,为了满足自己一些想当然的爱好,这是不必要的,有可能错误的。
比如掉电保护的时候想保存一些变量, 但改startup.a51来实现是很笨的方法,实际只要利用非变量区域的特性,定义一个指针变量指向堆栈低部:0xff处就可实现。
, 为什么还要去改? 可以这么说:任何时候都可以不需要改startup.a51,如果你明白它的特性本文来自CSDN博客,转载请标明出处:/jiazhen/archive/2007/12/25/1966124.aspx扩展阅读:dATa: 固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。
iData
iData篇一:idata-xdata,data区别在51系列中data,idata,xdata,pdata的区别在51系列中data,idata,xdata,pdata的区别 data:固定指前面0x00-0x7f 的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。
idata:固定指前面0x00-0xff的256个RAM,其中前128和data的128完全相同,只是因为访问的方式不同。
idata是用类似C中的指针方式访问的。
汇编中的语句为:mox ACC,@Rx.(不重要的补充:c中idata做指针式的访问效果很好) xdata:外部扩展RAM,一般指外部0x0000-0xffff空间,用DPTR访问。
pdata:外部扩展RAM 的低256个字节,地址出现在A0-A7的上时读写,用movx ACC,@Rx读写。
这个比较特殊,而且C51好象有对此BUG, 建议少用。
但也有他的优点,具体用法属于中级问题,这里不提。
startup.a51的作用和汇编一样,在C中定义的那些变量和数组的初始化就在startup.a51中进行,如果你在定义全局变量时带有数值,如unsigned char data xxx=“100”;,那startup.a51中就会有相关的赋值。
如果没有=100,startup.a51就会把他清0。
(startup.a51==变量的初始化)。
这些初始化完毕后,还会设置SP指针。
对非变量区域,如堆栈区,将不会有赋值或清零动作。
有人喜欢改startup.a51,为了满足自己一些想当然的爱好,这是不必要的,有可能错误的。
比如掉电保护的时候想保存一些变量, 但改startup.a51来实现是很笨的方法,实际只要利用非变量区域的特性,定义一个指针变量指向堆栈低部:0xff处就可实现。
, 为什么还要去改? 可以这么说:任何时候都可以不需要改startup.a51,如果你明白它的特性。
c语言指针详细讲解
c语言指针详细讲解
C 语言中指针是非常强大的概念,它允许程序直接访问内存中的数据。
指针在 C 语言中最初是被用于解决内存分配问题而提出的,随着 C 语言的发展,指针也变得愈发重要。
指针的本质是一个存储变量地址的变量。
在 C 语言中,指针通常用符号&来表示,例如&x 表示的是 x 变量的地址。
指针变量存储的是一个内存地址,当程序读取指针变量时,它会读取该地址中存储的数据。
C 语言中可以使用指针进行高效的内存操作。
例如,当程序需要对一个数组元素进行修改时,可以直接用指针修改该元素的值,而不必修改数组名本身。
另外,指针还可以用于动态分配内存,这是 C 语言中一个重要的特性。
指针的使用方法比较灵活,但也需要小心使用。
如果不小心处理指针,可能会导致未知的错误。
例如,当指针指向的内存空间被释放后,程序试图访问该内存空间时可能会导致未定义的行为。
因此,在C 语言中,指针的使用需要更加谨慎。
C 语言中指针是一个非常重要和强大的概念,掌握指针的使用方法可以让程序员写出更加高效和安全的代码。
51单片机的idataxdatapdatadata的详解
data: 固定指前面0x00-0x7f的128个RA M,可以用acc直接读写的,速度最快,生成的代码也最小。
bit :是指0x20-0x2f的可位寻址区idata:固定指前面0x00-0xff的256个RA M,其中前128和dATa的128完全相同,只是因为访问的方式不同。
idata是用类似C中的指针方式访问的。
汇编中的语句为:mox ACC,@Rx.(不重要的补充:c中idAT a做指针式的访问效果很好) xdATa:外部扩展RA M,一般指外部0x0000-0xffff空间,用DPTR访问。
pdATa:外部扩展RA M的低256个字节,地址出现在A0-A7的上时读写,用movxACC,@ Rx读写。
这个比较特殊,而且C51好象有对此B UG, 建议少用。
但也有他的优点,具体用法属于中级问题,这里不提。
startu p.a51的作用,和汇编一样,在C中定义的那些变量和数组的初始化就在st artup.a51中进行,如果你在定义全局变量时带有数值,如unsig ned char dATa xxx="100";,那start up.a 51中就会有相关的赋值。
如果没有=100,startu p.a51就会把他清0。
(startu p.a51==变量的初始化)。
这些初始化完毕后,还会设置SP指针。
对非变量区域,如堆栈区,将不会有赋值或清零动作。
有人喜欢改s tartu p.a51,为了满足自己一些想当然的爱好,这是不必要的,有可能错误的。
比如掉电保护的时候想保存一些变量, 但改star tup.a51来实现是很笨的方法,实际只要利用非变量区域的特性,定义一个指针变量指向堆栈低部:0xff处就可实现。
, 为什么还要去改? 可以这么说:任何时候都可以不需要改start up.a51,如果你明白它的特性。
data及code详解
51单片机的data,xdata,code(2012-03-05 09:55:23)转载▼标签:杂谈dATa: 固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。
idATa:固定指前面0x00-0xff的256个RAM,其中前128和dATa的128完全相同,只是因为访问的方式不同。
idATa是用类似C中的指针方式访问的。
汇编中的语句为:mox ACC,@Rx.(不重要的补充:c中idATa做指针式的访问效果很好)xdATa: 外部扩展RAM,一般指外部0x0000-0xffff空间,用DPTR访问。
pdATa: 外部扩展RAM的低256个字节,地址出现在A0-A7的上时读写,用movx ACC,@Rx读写。
这个比较特殊,而且C51好象有对此BUG, 建议少用。
但也有他的优点,具体用法属于中级问题,这里不提。
startup.a51 的作用,和汇编一样,在C中定义的那些变量和数组的初始化就在startup.a51中进行,如果你在定义全局变量时带有数值,如unsigned char dATa xxx="100";,那startup.a51中就会有相关的赋值。
如果没有=100,startup.a51就会把他清0。
(startup.a51 ==变量的初始化)。
这些初始化完毕后,还会设置SP指针。
对非变量区域, 如堆栈区,将不会有赋值或清零动作。
有人喜欢改startup.a51,为了满足自己一些想当然的爱好,这是不必要的,有可能错误的。
比如掉电保护的时候想保存一些变量, 但改startup.a51来实现是很笨的方法,实际只要利用非变量区域的特性,定义一个指针变量指向堆栈低部:0xff处就可实现。
, 为什么还要去改? 可以这么说:任何时候都可以不需要改startup.a51,如果你明白它的特性。
bit是在内部数据存储空间中20H .. 2FH 区域中一个位的地址,这在DATA的20H以后以字节形式出现,可互相参照。
51单片机的data,idata,xdata,pdata的详解
一般的教科书里RAM大小是指默认用户RAM,但是很少有特别说明的;于是就造成了问题遗留下来C51:片内用户RAM有128字节(位于片内所有RAM的低128B,高128B是SFR)访问RAM可以使用直接或者间接寻址方式,地址为00H-7FH,在80H-FFH的空间分配给了SFR,只能使用直接寻址方式。
C52:片内用户RAM为256字节(位于片内所有RAM的低128B,高128B是SFR和用户RAM)低128字节(00H-7FH)的访问方式为直接和间接寻址方式;高128字节(地址80H-FFH)只能使用间接寻址方式。
SFR的地址也为80H-FFH,但只能使用直接寻址方式。
也就是说,C52的高128B是用户RAM和SFR统一编制,共享地址,通过指令的寻址方式不同来进行区分。
1、80C51单片机存贮空间的分配空间名称地址范围说明DATA D:00H~7FH片内RAM直接寻址区BDATA D:20H~2FH片内RAM位寻址区IDATA I:00H~FFH片内RAM间接寻址区XDATA X:0000H~FFFFH64KB常规片外RAM数据区HDATA X:0000H~FFFFFFH16MB扩展片外RAM数据区CODE C:0000H~FFFFH64K常规片内外ROM代码区HCONST(ECODE)C:0000H~FFFFFFH16MB扩展片外ROM常数区(Dallas390可用作代码区)BANK0~ BANK31B0:0000H~FFFFH~B31:0000H~FFFFH分组代码区,最大可扩展32X64KB ROM(1)data: 固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。
(2)bit :是指0x20-0x2f的可位寻址区。
(3)idata:固定指前面0x00-0xff的256个RAM,其中前128和dATa的128完全相同,只是因为访问的方式不同。
idata是用类似C中的指针方式访问的。
c语言中的指针详解
c语言中的指针详解在C语言中,指针是一种特殊的变量类型,它存储了一个变量的内存地址。
通过指针,我们可以间接访问和修改内存中的数据,这对于一些需要动态分配内存的操作非常有用。
以下是关于C语言指针的一些详细解释:1. 定义指针:使用"*"符号来定义指针变量。
例如,int* ptr; 定义了一个指向整型变量的指针 ptr。
2. 取址操作符(&):取地址操作符(&)用于获取变量的内存地址。
例如,&a 返回变量 a 的地址。
3. 解引用操作符(*):解引用操作符(*)用于访问指针所指向的变量的值。
例如,*ptr 返回指针 ptr 所指向的整型变量的值。
4. 动态内存分配:可以使用相关的库函数(如malloc和calloc)在运行时动态分配内存。
分配的内存可以通过指针来访问和使用,并且在使用完后应该使用free函数将其释放。
5. 空指针:空指针是一个特殊的指针值,表示指针不指向任何有效的内存地址。
可以将指针初始化为NULL来表示空指针。
6. 指针和数组:指针和数组在C语言中有密切的关系。
可以通过指针来访问数组元素,并且可以使用指针进行指针算术运算来遍历数组。
7. 传递指针给函数:可以将指针作为函数参数传递,以便在函数内部修改实际参数的值。
这种传递方式可以避免拷贝大量的数据,提高程序的效率。
8. 指针和字符串:字符串在C语言中实际上是以字符数组的形式表示的。
可以使用指针来访问和操作字符串。
需要注意的是,指针在使用时需要小心,因为不正确的操作可能导致程序崩溃或产生不可预料的结果。
对于初学者来说,理解指针的概念和使用方法可能需要一些时间和练习。
C51的指针类型
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)等价。
c++指针的定义
c++指针的定义摘要:一、C++指针的概念1.指针的定义2.指针的作用3.指针的类型二、C++指针的声明与初始化1.声明指针2.初始化指针三、C++指针的操作1.访问指针指向的值2.修改指针指向的值3.指针的运算四、C++指针的注意事项1.空指针2.指针的越界访问3.指针的安全使用正文:C++指针是C++编程中一个非常重要的概念,它允许我们间接访问内存中的数据。
指针可以被认为是一个存储变量地址的变量。
本文将详细介绍C++指针的定义、声明与初始化、操作以及注意事项。
一、C++指针的概念指针是一种特殊的变量,它存储的是另一个变量的内存地址。
在C++中,指针用*符号表示,它表示一个变量是指针类型。
指针类型可以是指向整数、浮点数、字符或者对象的。
1.指针的定义指针的定义格式为:类型名*指针名;例如:int *p;表示p是一个指向整数的指针。
2.指针的作用指针的作用是允许我们间接访问和操作内存中的数据。
通过指针,我们可以访问数组元素、对象成员等。
3.指针的类型指针的类型决定了它可以存储的变量类型的地址。
例如,int *p表示p是一个指向整数的指针,float *q表示q是一个指向浮点数的指针。
二、C++指针的声明与初始化在C++中,我们需要先声明指针,然后才能使用它。
声明指针时,需要指定指针的类型和名称。
初始化指针时,需要为指针分配内存空间,并将其指向一个已知的变量。
1.声明指针声明指针的格式为:类型名*指针名;例如:int *p;表示p是一个指向整数的指针。
2.初始化指针初始化指针的格式为:指针名= new 类型名(值);例如:int *p = newint(10);表示p是一个指向整数10的指针。
三、C++指针的操作指针的操作包括访问指针指向的值、修改指针指向的值以及指针的运算。
1.访问指针指向的值访问指针指向的值的格式为:指针名;例如:int *p = new int(10);则p指向的值为10。
2.修改指针指向的值修改指针指向的值的格式为:指针名= new 类型名(值);例如:int *p = new int(10);p->value = 20;则p指向的值变为20。
C语言指针用法详解
C语言指针用法详解C语言指针用法详解指针可以说是集C语言精华之所在,一个C语言达人怎么可以不会指针呢。
下面店铺给大家介绍C语言指针用法,欢迎阅读!C语言指针用法详解(1)关于指针与数组的存储a、指针和数组在内存中的存储形式数组p[N]创建时,对应着内存中一个数组空间的分配,其地址和容量在数组生命周期内一般不可改变。
数组名p本身是一个常量,即分配数组空间的地址值,这个值在编译时会替换成一个常数,在运行时没有任何内存空间来存储这个值,它和数组长度一起存在于代码中(应该是符号表中),在链接时已经制定好了;而指针*p创建时,对应内存中这个指针变量的空间分配,至于这个空间内填什么值即这个指针变量的值是多少,要看它在程序中被如何初始化,这也决定了指针指向哪一块内存地址。
b、指针和数组的赋值与初始化根据上文,一般情况下,数组的地址不能修改,内容可以修改;而指针的内容可以修改,指针指向的内容也可以修改,但这之前要为指针初始化。
如:int p[5];p=p+1; 是不允许的而p[0]=1; 是可以的;//int *p;p=p+1; 是允许的p[0]=1; 是不允许的,因为指针没有初始化;//int i;int *p=&i;p[0]=1; 是允许的;对于字符指针还有比较特殊的情况。
如:char * p="abc";p[0]='d'; 是不允许的为什么初始化了的字符指针不能改变其指向的内容呢?这是因为p 指向的是“常量”字符串,字符串"abc"实际是存储在程序的静态存储区的,因此内容不能改变。
这里常量字符串的地址确定在先,将指针指向其在后。
而char p[]="abc";p[0]='d'; 是允许的这是因为,这个初始化实际上是把常量直接赋值给数组,即写到为数组分配的内存空间。
这里数组内存分配在先,赋值在后。
(2)关于一些表达式的含义char *p, **p, ***p;char p[],p[][],p[][][];char *p[],*p[][],**p[],**p[][],*(*p)[],(**p)[],(**p)[][];能清晰地知道以上表达式的含义吗?(知道的去死!)第一组:char *p, **p, ***p;分别为char指针;char*指针,即指向char*类型数据地址的指针;char**指针,即指向char**类型数据的指针;他们都是占4字节空间的指针。
单片机寄存器和指针的关系
单片机寄存器和指针的关系导言单片机(Microcontroller Unit,MCU)是一种功能强大且体积小巧的计算机系统,它集成了处理器、存储器和各种系统外设,用于控制电子设备的各种功能。
在单片机开发过程中,寄存器和指针是两个非常重要的概念。
寄存器是用于存储数据的特殊内存单元,而指针则是指向寄存器或其他内存位置的变量。
本文将深入探讨单片机寄存器和指针之间的关系以及它们在单片机编程中的应用。
寄存器和指针的基本概念寄存器寄存器是一种特殊的存储单元,通常用于存储和操作数据。
在单片机中,寄存器可以分为通用寄存器(General Purpose Register,GPR)和特殊功能寄存器(Special Function Register,SFR)两类。
通用寄存器是供程序员自由使用的寄存器,其值可以随意更改。
在程序中,我们可以将数据暂存到通用寄存器中,进行各种运算和操作。
通用寄存器的数量和位宽度可以根据单片机的型号和架构而有所不同。
特殊功能寄存器是用于访问和控制单片机内部外设的寄存器。
每个外设都有一组特殊功能寄存器,用于读取和设置外设的各种参数和状态。
通过操作特殊功能寄存器,程序可以与外设进行交互,实现各种功能。
特殊功能寄存器的地址通常被预定义,并有特定的名称,例如控制寄存器、状态寄存器等。
指针指针是一种特殊的变量,它存储了一个地址,指向内存中的某个位置。
单片机中的指针可以用来访问寄存器和其他内存位置的数据。
通过使用指针,我们可以直接操作特定地址上的数据,而不需要将数据加载到寄存器中。
这样,我们可以节省寄存器的使用,提高代码的效率和灵活性。
指针在单片机编程中起到了非常重要的作用。
我们可以通过定义指针来访问特殊功能寄存器,读取或修改其值。
此外,指针还可以用于访问其他内存位置的数据,例如缓冲区或数组。
寄存器和指针是密切相关的,它们在单片机编程中有着紧密的联系。
指针访问寄存器在单片机编程中,我们可以使用指针来直接访问寄存器的值。
指针的详细讲解
指针的详细讲解
指针是C语言中重要的概念,也是很多初学者比较困惑的一部分。
在C语言中,指针是一个特殊的数据类型,它直接或者间接地指向了另一个变量或者数据的地址。
指针的基本定义:指针是一个变量,其值是扮演着另一个变量名也就是地址的变量的地址。
指针与变量之间的区别在于,变量存储的是实际的值,而指针存储的是值的内存地址。
指针的类型:在C语言中,指针有不同的类型,这些类型标识了指针指向的变量的数据类型。
例如,int*是一个整数指针,而char*是一个字符指针。
指针的运算:指针可以进行加、减、前后移动等操作。
例如,指针加上一个整数就会指向另一个地址,指针减去一个整数就会回到前一个地址。
指针的使用:指针的主要作用是通过引用来访问变量或者数据。
通过指针,我们可以传递变量的地址而不是变量本身,这样可以减少内存的使用量并提高程序的效率。
指针的注意事项:在使用指针时,需要特别注意指针的安全性。
不正确的使用指针可能会导致内存泄漏、程序崩溃、数据丢失等问题。
总的来说,指针是C语言中一个非常重要的概念,理解它的基本概念和使用方法,对于C语言的学习和开发都有非常重要的意义。
C语言进阶-第四讲 存储器与指针
第四讲存储器与指针(Memory & Pointer)凌明trio@ Ver2.0 2008.3.31东南大学国家专用集成电路系统工程技术研究中心目录存储器,还是存储器!内存陷阱!动态内存分配算法动态内存分配代码讲解2.1 指针的基本概念2.1.1 指针是什么?指针是一个变量,它的值是另外一个变量的地址。
例12.1.2 指针的类型指针所存储的那个变量类型,就称为指针的类型。
例2 有三个不同类型的指针:int I[2], *pI = &I[0]; 右边的三个运算有何不同?pI++;char C[2], *pC = &C[0]; pC++;float F[2], *pF = &F[0];pF++;0x00C7指针变量int *p0x00C7变量int a上面例中的两个0x00C7有什么区别?2.1.3 指针的三个要素1.指针指向的地址(指针的内容);2.指针指向的地址上的内容;3.指针本身的地址。
例3:int A, *pA, **ppA;pA = &A;ppA = &pA;在复杂的指针都可以通过下表来分析:&ppA ppA *ppA **ppA&pApA*pA&A A第二章指针2.1.4 指针的大小(指针变量占用的内存空间)与所用的CPU 寻址空间大小和类型有关,而与指针类型无关。
8位CPU 的指针长度为1~2个字节(51单片机的情况较为复杂,是1~3个字节);16位CPU 的指针长度为2个字节(如MSP430);32位CPU 的指针长度为4个字节(如Intel 80386)。
上面所述是通常情况,并不是全部符合。
2.1.5 指针的初始化变量在没有赋值之前,其值不定的。
对于指针变量,可以表述为:指向不明。
程序访问了一个没有初始化的指针:int* p;p 的内存是随机的一个数,比如:0x3FF0073D程序随即访问内存地址:0x3FF0073D0x3FF0073D 是哪里的内存?说不定正好是Windows 老大要用的内存,你竟敢访问!Windows 一生气,蓝屏。
单片机中关键字data,idata,xdata,pdata,bdata
单片机中关键字data,idata,xdata,pdata,bdatadata:固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。
idata:固定指前面0x00-0xff的256个RAM,其中前128和data的128完全相同,只是因为访问的方式不同。
idata是用类似C中的指针方式访问的。
汇编中的语句为:mox ACC,@Rx.(不重要的补充:c中idata做指针式的访问效果很好)xdata:外部扩展RAM,一般指外部0x0000-0xffff空间,用DPTR访问。
pdata:外部扩展RAM的低256个字节,地址出现在A0-A7的上时读写,用movx ACC,@Rx读写。
这个比较特殊,而且C51好象有对此BUG, 建议少用。
但也有他的优点,具体用法属于中级问题,这里不提。
startup.a51的作用和汇编一样,在C中定义的那些变量和数组的初始化就在startup.a51中进行,如果你在定义全局变量时带有数值,如unsigned char dataxxx="100";,那startup.a51中就会有相关的赋值。
如果没有=100,startup.a51就会把他清0。
(startup.a51 ==变量的初始化)。
这些初始化完毕后,还会设置SP指针。
对非变量区域,如堆栈区,将不会有赋值或清零动作。
有人喜欢改startup.a51,为了满足自己一些想当然的爱好,这是不必要的,有可能错误的。
比如掉电保护的时候想保存一些变量, 但改startup.a51来实现是很笨的方法,实际只要利用非变量区域的特性,定义一个指针变量指向堆栈低部:0xff处就可实现。
, 为什么还要去改? 可以这么说:任何时候都可以不需要改startup.a51,如果你明白它的特性dATa: 固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。
c语言中指针的概念
c语言中指针的概念
C语言中的指针是一种特殊的变量,它用来存储另一个变量的
内存地址。
指针可以指向任何类型的数据,包括基本类型(如整数和字符)和复合类型(如结构体和数组)。
使用指针可以实现对变量的间接访问,通过改变指针的值来修改变量的值。
指针与变量之间的关系可以看作指针指向了变量所在的内存地址,通过该地址可以访问变量的值。
在C语言中,通过使用取地址操作符“&”来获取变量的内存地址,并使用解引用操作符“*”来访问指针变量指向的内存地址
中存储的值。
指针的主要作用包括以下几个方面:
1. 动态分配内存:使用指针可以在程序运行时动态地分配内存,例如使用malloc函数分配堆内存。
2. 传递参数:指针可以作为函数的参数,通过传递指针可以在函数内部直接修改传入的变量的值。
3. 使用数组:指针可以用于访问和操作数组的元素,通过指针变量和指针运算可以实现对数组的遍历和修改。
4. 构建数据结构:通过指针可以构建复杂的数据结构,如链表、树等。
尽管指针在C语言中具有强大和灵活的功能,但也容易引发
一些常见的错误,如空指针引用、野指针引用和内存泄漏等。
因此,在使用指针时,需要小心处理,确保指针的正确性和安全性。
C51如何使用指针变量剖析
MOVX 就是用来读写外部RAM的MOVC 读写外部ROM可通过检测RI来判断RXD是否有信息C语言参考资料:指针类型和存储区的关系详解一、存储类型与存储区关系data ---> 可寻址片内rambdata ---> 可位寻址的片内ramidata ---> 可寻址片内ram,允许访问全部内部rampdata ---> 分页寻址片外ram (MOVX @R0 (256 BYTE/页xdata ---> 可寻址片外ram (64k 地址范围code ---> 程序存储区 (64k 地址范围,对应MOVC @DPTR二、指针类型和存储区的关系对变量进行声明时可以指定变量的存储类型如:uchar data x和data uchar x相等价都是在内ram区分配一个字节的变量。
同样对于指针变量的声明,因涉及到指针变量本身的存储位置和指针所指向的存储区位置不同而进行相应的存储区类型关键字的使用如:uchar xdata * data pstr是指在内ram区分配一个指针变量("*"号后的data关键字的作用,而且这个指针本身指向xdata区("*"前xdata关键字的作用,可能初学C51时有点不好懂也不好记。
没关系,我们马上就可以看到对应“*”前后不同的关键字的使用在编译时出现什么情况。
......uchar xdata tmp[10]; //在外ram区开辟10个字节的内存空间,地址是外ram的0x0000-0x0009......第1种情况:uchar data * data pstr;pstr=tmp;首先要提醒大家这样的代码是有bug的, 他不能通过这种方式正确的访问到tmp空间。
为什么?我们把编译后看到下面的汇编代码:MOV 0x08,#tmp(0x00 ;0x08是指针pstr的存储地址看到了吗!本来访问外ram需要2 byte来寻址64k空间,但因为使用data关键字(在"*"号前的那个,所以按KeilC编译环境来说就把他编译成指向内ram的指针变量了,这也是初学C51的朋友们不理解各个存储类型的关键字定义而造成的bug。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《指针类型和存储区的关系详解》作者:心意无涯?
--- 摘自《C51BBS离线版光盘》---
指针类型和存储区的关系详解
一、存储类型与存储区关系
data ---> 可寻址片内ram
bdata ---> 可位寻址的片内ram
idata ---> 可寻址片内ram,允许访问全部内部ram
pdata ---> 分页寻址片外ram (MOVX @R0) (256 BYTE/页)
xdata ---> 可寻址片外ram (64k 地址范围)
code ---> 程序存储区 (64k 地址范围),对应MOVC @DPTR
二、指针类型和存储区的关系
对变量进行声明时可以指定变量的存储类型如:
uchar data x和data uchar x相等价都是在内ram区分配一个字节的变量。
同样对于指针变量的声明,因涉及到指针变量本身的存储位置和指针所指向的存储区位置不同而进行
相应的存储区类型关键字的
使用如:
uchar xdata * data pstr
是指在内ram区分配一个指针变量("*"号后的data关键字的作用),而且这个指针本身指向xdata区("*"前xdata关键字的作用),
可能初学C51时有点不好懂也不好记。
没关系,我们马上就可以看到对应“*”前后不同的关键字的使用在编译时出现什么情况。
......
uchar xdata tmp[10]; //在外ram区开辟10个字节的内存空间,地址是外ram的0x0000-0x0009 ......
第1种情况:
uchar data * data pstr;
pstr=tmp;
首先要提醒大家这样的代码是有bug的, 他不能通过这种方式正确的访问到tmp空间。
为什么?我们把编译后看到下面的汇编
代码:
MOV 0x08,#tmp(0x00) ;0x08是指针pstr的存储地址
看到了吗!本来访问外ram需要2 byte来寻址64k空间,但因为使用data关键字(在"*"号前的那个),所以按KeilC编译环境来说
就把他编译成指向内ram的指针变量了,这也是初学C51的朋友们不理解各个存储类型的关键字定义而造成的bug。
特别是当工程中的
默认的存储区类为large时,又把tmp[10] 声明为uchar tmp[10] 时,这样的bug是很隐秘的不容易被发现。
第2种情况:
uchar xdata * data pstr;
pstr = tmp;
这种情况是没问题的,这样的使用方法是指在内ram分配一个指针变量("*"号后的data关键字的作用),而且这个指针本身指向
xdata区("*"前xdata关键字的作用)。
编译后的汇编代码如下。
MOV 0x08,#tmp(0x00) ;0x08和0x09是在内ram区分配的pstr指针变量地址空间
MOV 0x09,#tmp(0x00)
这种情况应该是在这里所有介绍各种情况中效率最高的访问外ram的方法了,请大家记住他。
第3种情况:
uchar xdata * xdata pstr;
pstr=tmp;
这中情况也是对的,但效率不如第2种情况。
编译后的汇编代码如下。
MOV DPTR, #0x000A ;0x000A,0x000B是在外ram区分配的pstr指针变量地址空间
MOV A, #tmp(0x00)
MOV @DPTR, A
INC DPTR
MOV A, #tmp(0x00)
MOVX @DPTR, A
这种方式一般用在内ram资源相对紧张而且对效率要求不高的项目中。
第4种情况:
uchar data * xdata pstr;
pstr=tmp;
如果详细看了第1种情况的读者发现这种写法和第1种很相似,是的,同第1 种情况一样这样也是有bug的,但是这次是把pstr分
配到了外ram区了。
编译后的汇编代码如下。
MOV DPTR, #0x000A ;0x000A是在外ram区分配的pstr指针变量的地址空间
MOV A, #tmp(0x00)
MOVX @DPTR, A
第5种情况:
uchar * data pstr;
pstr=tmp;
大家注意到"*"前的关键字声明没有了,是的这样会发生什么事呢?下面这么写呢!对了用齐豫的一首老歌名来说就是“请跟我
来”,请跟我来看看编译后的汇编代码,有人问这不是在讲C51吗?为什么还要给我们看汇编代码。
C51要想用好就要尽可能提升C51
编译后的效率,看看编译后的汇编会帮助大家尽快成为生产高效C51代码的高手的。
还是看代码吧!
MOV 0x08, #0X01 ;0x08-0x0A是在内ram区分配的pstr指针变量的地址空间
MOV 0x09, #tmp(0x00)
MOV 0x0A, #tmp(0x00)
注意:这是新介绍给大家的,大家会疑问为什么在前面的几种情况的pstr指针变量都用2 byte空间而到这里就用3 byte空间了
呢?这是KeilC的一个系统内部处理,在KeilC中一个指针变量最多占用 3 byte空间,对于没有声明指针指向存储空间类型的指针,
系统编译代码时都强制加载一个字节的指针类型分辩值。
具体的对应关系可以参考KeilC的help中C51 User''s Guide。
第6种情况:
uchar * pstr;
pstr=tmp;
这是最直接最简单的指针变量声明,但他的效率也最低。
还是那句话,大家一起说好吗!编译后的汇编代码如下。
MOV DPTR, #0x000A ;0x000A-0x000C是在外ram区分配的pstr指针变量地址空间
MOV A, #0x01
MOV @DPTR, A
INC DPTR
MOV DPTR, #0x000A
MOV A, #tmp(0x00)
MOV @DPTR, A
INC DPTR
MOV A, #tmp(0x00)
MOVX @DPTR, A
这种情况很类似第5种和第3种情况的组合,既把pstr分配在外ram空间了又增加了指针类型的分辨值。
小结一下:大家看到了以上的6种情况,其中效率最高的是第2种情况,既可以正确访问ram区又节约了代码,效率最差的是第 6
种,但不是说大家只使用第2种方式就可以了,还要因情况而定,一般说来应用51系列的系统架构的内部ram 资源都很紧张,最好大家
在定义函数内部或程序段内部的局部变量使用内ram,而尽量不要把全局变量声明为内ram区中。
所以对于全局指针变量我建议使用第
3 种情况,而对于局部的指针变量使用第2种方式。
C51是很灵活的,也很好理解和使用,但要成为笑傲江湖的一代高手还是要多想多练,没有实际项目的锻炼是不容易提高的。
希
望这篇文章对大家一点用处。