嵌入式技术
当我们将一个指针变量定义好之后,接下来需要考虑的问题就是如何来使用这个指针变量了。前面学习普通变量的时候,我们知道,一个变量的操作其实就是分成读和写两个步骤。而指针变量在平时使用的时候,也是主要分成读和写两个操作步骤,不同于常规变量的是,指针变量的赋值运算其实是写入一个普通变量的地址,我们将这一个过程称为指针变量的“指向操作”。而对指针变量读取的时候,由于指针变量存放的是某一个变量的地址,而读取某一个地址这个操作往往是没有意义的,因此在指针变量读取的时候,大多数情况我们都是读取指针变量指向的那个变量里面的内容。
指针变量的指向操作,其实就是将定义好的一个指针变量指向某一个变量或者内存区域,其方式为:“数据类型 *指针变量名 = &指向的变量;“。当然也可以先定义指针,再将其指向某一个变量,即:
“数据类型 *指针变量;
指针变量 = &指向的变量;“
在使用时,一定要注意上面“*“号的用法差异。还需要注意的是,一个指针变量只能指向与其数据类型相同的变量。
一旦一个指针指向某一个变量之后,操作这个指针变量就如同操作其指向的那个变量了。在操作时,我们使用“*指针变量名“的形式进行读取和写入,就等同于对指针所指向变量的读和写操作。指针变量指向变量的读取如图1所示。
图1 指针变量指向变量的读取
同时,指针变量指向变量的赋值如图2所示。
图2指针变量指向变量的赋值
由图1和图2中我们可以看出,当指针变量p指向了变量a之后,使用*p进行操作,就如同在操作变量a。以上就是指针变量的操作,非常简单。
需要注意的是,当一个指针被定义好之后,一定要对其进行初始化,即指向某一个变量的地址,没有指向任何变量的指针被称为“空指针”,空指针无法去做任何操作,一旦对空指针进行赋值,那么编译出来的程序将会无法使用,如图3所示。
图3 指针未指向变量输出错误
这种没有指向任何变量的指针被称为“野指针“,注意不是”空指针“,空指针和野指针是不一样的指针,野指针是非法的,空指针是合法的,关于空指针和野指针的区别为:
野指针是不知道指向什么地方的指针,它的出现主要原因是没有对指针进行初始化,或者指针所指向的内存块被释放之后,没有将该指针设置成空指针。
空指针是指指向NULL的指针,NULL为C语言定义的宏,为0,关于空指针我们后面会详细讲解。
我们前面说过,一个变量的地址是当我们在定义这个变量时由编译器主动随机分配的,因此如果我们在定义一个指针变量之后,随意地对其赋值,对于用户来说,我们不清楚那一块内存地址可用,那一块不可用。那么这样操作是不是就是不合法的呢?其实并不是,比如我们在做单片机的时候,某一个外设的地址你可以从数据手册上面查到,那么我们此时要定义一个指针来指向这个地址,以便给后续的程序使用,那么这种情况下,我们势必需要显示地将一个地址赋值给这个指针变量。反过来说,指针就是由于可以任意地指向任何地方,所以一旦使用不当,比如将一个指针指向一些受保护的内存块并且修改这一块内容,那么会引起一些不可估量的错误。
如果对一个指针贸然地赋值一个常量,那么编译器会不知所措,在这种不知所措之下,编译器只会报一个警告,这个警告的中文意思就是,将一个int类型的变量赋值给一个(int *)类型的变量,如图4所示。
图4 给指针赋值一个常量
正确的做法是,我们需要将这个常量强制转换成一个指针类型,关于强制类型转换其实很简单,只需要将这个变量或者常量前面用括号加一个你所需要转换的类型即可。如图5所示。
图5 给指针赋值一个常量地址
现在我们来做一个实例,先定义一个变量a,假设这个变量a的地址是我们硬件某一个外设的地址,我们可以先编程获取其地址,如图6所示。
图6 获取某一个变量的地址
接着,我们来定义一个指针变量,并且显示地将这个地址赋值给这个变量,接着,对这个指针所指向的内存进行赋值,我们来看看最终变量a里面的内容是否会跟着改变。既然模拟的是硬件,那么此时有个小提示需要注意,我们一定要用“volatile“关键词来修饰这个内存区域。如图7所示。
图7 指针指向外设模拟
通过这个实验我们可以看出,只要指针使用合理,对它进行地址赋值是可以很方便地去使用某一个硬件外设的。
以上就是指针的简单应用,接下来的内容,我们正式开始学习指针。
全部0条评论
快来发表一下你的评论吧 !