在嵌入式系统中,对内存地址的操作是一个重要的方面,从广义上讲,嵌入式系统的地址空间可以分成以下三种类型:
系统的内存
处理器内部的寄存器映射
处理器外部部件的内存映射
从编程的角度看,嵌入式系统和PC系统的软件设计的一个重要的区别即在于嵌入式系统更重视对硬件的操作。而对硬件的操作需要通过操作内部寄存器和外围部件内存映射的地址实现,其实现方式都是通过对内存读、写两种操作。
在汇编语言中,各种处理器都有对内存的不同的寻址方式读写内存。在高级语言中,C语言是唯一可以进行内存操作的语言,C语言对内存的操作主要需要通过指针来完成。
1、使用指针操作内存
在C语言中,指针是一种非常重要的数据类型。使用指针变量可以表示各种数据结构,能很方便地使用数组和字符串,并能像汇编一样处理内存地址。指针的本质就是一个地址,在32位的系统中,指针是一个32位的无符号整数。指针可以用一个变量来表示,变量的指针实际上就是变量的地址。存放变量地址的变量是指针变量。一个指针变量的值就是某个变量的地址或称为某变量的指针。
一个简单的指针应用如下所示:
int a;
int *p = &a;
这个例子表示,整型指针型变量p指向a的地址,此时对*p的操作等同于对a的操作。
使用指针可以指向一个变量,也可以指向一个由malloc函数分配的内存,例如:
void *p = malloc(1024);
系统分配1024字节的内存,然后让变量p指向这块内存,即p的值是这1024字节的连续内存的地址。在程序中就可以通过p来操作这块内存区域。在内存使用完成后,需要使用free函数讲内存释放。
free(p);
在嵌入式系统中的程序开发中,指针的值除了以上的两种形式(从系统内存分配或者指向变量)以外,还可以使用绝对的数值。这是由于在嵌入式系统中,外设寄存器和外部部件的内存映射的地址空间可能都是固定的,因此可以使用指针来处理他们。
例如,如果需要在地址0x0040处写入一个字节的数据0xf0,可以使用如下的程序:
unsigned char *p = (unsigned char *)0x0040;
*p = 0xf0;
这个程序定义了一个指向0x0040地址的字节型的指针,然后向该地址写入数据0xf0。
上面的程序等同于:
*(unsigned char *)0x0040 = 0xf0;
所以说不使用指针变量也可以对实际的地址操作。读内存的程序与之类似,可以使用指针变量或者直接使用地址得到内存中的数据。
2、指针的类型
前面的程序在内存的一个指定的地址处写入一个字节(8位)的数据。如果需要写入两个字节(16位)的数据,需要改变指针类型。例如:同样向地址0x0040处写入两个字节的数据0x0f0f,需要使用如下的语句:
*(unsigned short*)0x0040 = 0x0f0f;
在这个语句中,使用unsigned short而不使用unsigned char,short在C语言中代表16位的整数。
如果写入4个字节(32位)的数据,则需要使用一下的程序:
*(unsigned long*)0x0040 = 0xf0f0f0f0;
在这个语句中,使用unsigned long,long在C语言中代表32位的整数。
在32位的系统中,一般编译器认为int代表是32位的整数,等同于long,所以习惯使用int代替long作为内存操作的数据类型。
注意:指针的类型决定了使用指针进行读写操作时每次读写字节的数目。
3、指针的增量
在对指针变量的操作中,有时需要对指针变量进行加减运算。例如:
unsigned char *p = (unsigned char *)0x0040;
P++;
*p = 0xf0;
这段程序的含义是向地址0x0041的字节处写入数据0xf0。
指针加减运算的含义是:指针的单位增量(或减量)等于指针类型所占的内存量。
对指针进行增量操作的使用,增加的单位是以指针类型的大小:char类型的增量表示增加1字节的内存,short表示增加2字节的内存,long和int表示增加4字节的内存,这些工作是编译器根据指针的类型自动完成的。
总结:对指针进行加减运算的时候,它的变化量与指针的类型有关。
4、指针的类型转换
在C语言中,指针的类型可以在使用的时候进行转换。指针的本质是一个地址,在32位系统中,指针就是一个32位无符号的整数。因此,各种指针都可以相互转化,而且指针在转换过程并没有任何实质性的变化,只是告诉编译器,目前的指针指向何种的内存区域。
在嵌入式系统中,处理器的片内设备一般都会映射到处理器的地址空间中。这些寄存器有可能是32位的,有可能只有8位,这时就需要使用C语言中不同类型的指针。
总结:指针的本质是一个无符号的整数,各个类型的指针都可以进行相互转换。
责任编辑:haq
暂无评论哦,快来评论一下吧!