指针初认识(二)

上篇我们简要介绍了内存和地址的关系,并由此提出了指针的概念。接下来我们一起深入了解有关指针的具体内容:

一、未初始化和非法的指针

下面这个代码说明了一个极为常见的错误:

int  *a;
*a = 12;

这个声明创建了一个名叫a的指针,后面那条赋值语句把12存储在a所指向的内存位置。值得注意的是,我们声明了这个变量,但从未对它进行初始化,所以我们没有办法预测12这个值将存储在什么地方。无论变量是静态的,还是动态的,声明一个指向整型的指针都不会“创建”用于存储整型值的内存空间。
注意:一个更为严重的情况是:这个指针偶尔可能包含了一个合法地址。接下来的事很简单:位于那个位置的值被修改,虽然你并无意去修改它。像这种类型的错误非常难以捕捉,因为引发错误的代码可能与原先用于操作那个值得代码完全不相干。所以,在对指针进行间接访问之前,必须确保它们已经被初始化。

二、NULL指针

标准定义了NULL指针,它作为一个特殊的指针变量,表示不指向任何东西。要使一个指针变量为NULL,你可以给他赋一个零值。为了测试一个指针变量是否为NULL,你可以将它与零值进行比较。之所以选择零这个值是一种源代码约定。就机器内部而言,NULL指针的实际值可能与此不同。
NULL指针的概念是非常有用的,因为它给了一种方法,表示某个特定的指针目前并未指向任何东西。例如,一个用于在某个数组中查找某个特定值的函数可能返回一个指向查找到的数组元素的指针。如果该数组不包含指向条件的值,函数就返回一个NULL指针。
对指针进行解引用操作就可以获得它所指向的值。但从定义上看,NULL指针并未指向任何东西。因此,对一个NULL指针进行解引用操作是非法的。在对指针进行解引用操作之前,你首先必须确保它并非NULL指针。
注意:如果你已经知道指针被初始化为什么地址,就把他初始化为改地址,否则就把它初始化为NULL。

三、指针变量和指针常量

首先我们从下面几条代码开始分析:

int  a;
int  *d = &a;
*d = 10 - *d;
d = 10 - *d;
*&a = 25;
*100 = 25

第3条语句中包含了两个间接操作符。右边的间接访问作为右值使用,所以它的值是d所指向的位置所存储的值(a的值)。左边的间接访问作为左值使用,所以d所指向的位置(a)把赋值符右侧的表达式的计算结果作为它的新值。
第4条语句是非法的,原因在于它把一个整型数据(10-*d)存储在一个指针变量中。(即实际使用的变量类型和应该使用的变量类型不一致)
注意:指针变量可以作为左值使用,并不是因为它们是指针,而是因为它们是变量。间接访问指定了一个特定的内存位置,这样我们便可以把间接访问表达式的结果作为左值使用。
第5条语句&操作符产生变量a的地址,它是一个指针常量。接着,*操作符访问其操作数所表示的地址。在这个表达式中操作数是a的地址,所以值25就存储在a中。
假定变量a存储于位置100,那么第6条语句看上去像是把25赋值给 a,但是,这条语句实际上是非法的,因为字面值100的类型是整型,而间接访问操作只能用于指针类型的表达式,如果非得把25存储于位置100,就必须使用强制类型转换。
即:*(int *)100 = 25
这次的分享就到这里,下篇我将进一步介绍指针的指针和基本的指针表达式!!!

猜你喜欢

转载自blog.csdn.net/sqrt_2/article/details/79555919