关于指针的三个容易弄混淆的概念及发散~~~

对于指针来讲,有3个比较容易混淆的概念:

  1. 指针地址
  2. 指针保存的地址
  3. 指针所保存的地址的值

在这里,我们分别来看看他们的定义:

  • 指针地址:指针自身的地址,即内存中用于存放指针变量的内存地址
  • 指针保存的地址:指针所保存的变量在内存中的地址,通俗讲就是指针所指向的对象的内存地址
  • 指针所保存的地址的值:指针所指对象的数值。

下面,我们用一个具体的例子来看看上面仨个东东的不同~~~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
int main()
{
    int i;
    int *p=0; //初始化指针p
    cout<<"i的地址为:"<<&i<<endl;
    cout<<"p的值为:"<<p<<endl;
    cout<<"p的内存地址为:"<<&p<<endl;
    i=3;
    cout<<"i的地址为:"<<&i<<endl;
    cout<<"i的值为:"<<i<<endl;
    p=&i;
    cout<<"p的值为:"<<p<<endl;
    cout<<"p的内存地址为:"<<&p<<endl;
    cout<<"p所指向的值为:"<<*p<<endl;
    *p=5;
    cout<<"p所指向的变成:"<<*p<<endl;
    cout<<"此时i的值变成:"<<i<<endl;
    return 0;
}

程序分析:

       在程序的5,6行,我们定义了一个变量i,和一个指针*p,同时将这个指针初始化为0。然后我们采用&运算符来得到整型变量i的地址,并输出之。后面两句关于p的值和内存就是初始化该指针时系统自动为其分配的地址和值(假设p的内存地址为B);

       在程序的第10行中,我们将3赋与i,这时i的地址并没有发生变化。比如说如果原来i的地址为A,这是i的地址仍然为A,只不过该地址A中间的值已经成为了3。那么后面两句的输出就显而易见了,i的地址输出应该为A,i的值为3;

       在程序的第13行,我们利用取地址运算符&将i的地址赋给了p,那么这个时候,p中的值应该就是i的地址,即为A。而p的内存地址并没有发生改变,仍然为B。在这里,我们就可以看到,对于指针p来讲:

  • p的值即为该指针p所保存的整型变量i的地址A
  • 指针p的地址还是原来初始化时候的内存地址B
  • 而利用间接运算符*访问并读取到得i得值即为i的值,也就是3

所以说在这里,指针地址就是B,指针保存的地址就是A,指针所保存的地址的值就是3

       在程序的17行,我们利用了指针可以随意修改指向对象的值得功能,将i中的值修改成了5,那么相应地输出p和i的值就应该是5了

综上所述,该程序的输出为

1

从这个输出上我们就可以明显看出上面三个概念本质上的区别了。

注释:

         我们在最开始定义一个指针的时候,最应该做的就是先将这个指针变量进行初始化,以防止它变成“野指针”。因为一个野指针可以指向任何内存地址,并且可以对该地址中的数值进行随意地修改或删除,这样很可能对整个程序造成不良后果!所以在定义指针的时候,一定要先将其初始化成0,即上面函数中的“int *p=0”。这样就会把这个指针的值限定成为0,从指针中的概念而不会引发野指针的问题。

         们在这里分析一下造成这种原因的机理。(注:在这里的矩形分别代表了整型变量i和指针变量p。矩形框中间的大矩形代表了该变量的数值,而小矩形代表了该变量的地址。)我们可以看到,如蓝色的笔所示,i的地址为A,p的地址为B。现在有绿色的笔标出了程序第13行中的语句,将i的地址赋给p,那么如右图所示,p里面的值就成为了i的地址A。在看看红笔。我们采用了间接运算符*访问i的值。正如红线所标示的一样,首先,它从p的值中找到i的地址为A,然后在从i的地址中读取到i的值为3。这样,就完成了利用指针p读取整型变量i的值了。

         这也是为什么我们在程序之初需要对指针p进行初始化的原因了。从上面可以看出,只要*p修改了i的值,那么连i自己也会把自己的值从3修改到了5。这就好比是我通过地址找到你家,然后我在你家里面把你家的电视机拿了,那么你家就真没有电视机了~~~虽然我举得这个例子不是很恰当,但是这个就是指针能干的事情啊,囧啊~~~    
        另外,程序第13行和程序第17行的位置千万不要搞颠倒了哈。这里面是有逻辑顺序的。首先我们需要向指针p说明变量i的地址(p=&i),之后我们才能对其进行操作(*p=5)。这里绝对不可能是先操作了再找地址,这肯定是不符合逻辑的。如果程序这样写,在编译的时候不会犯错,但是运行的时候错误就出来了,如下:

2

好了,收工~~~

posted @ 2017-05-26 15:47  杨铭宇  阅读(224)  评论(0编辑  收藏  举报
友情链接:回力球鞋 | 中老年女装 | 武汉英语学校 | 雅思备考 | 托福备考