指针与二级指针

来源:互联网 发布:用excel做统计图的数据 编辑:程序博客网 时间:2024/06/08 09:17
为了把引用 解引用 取地址 指针 双指针 指针的引用 二级指针 这一块弄清楚,钻研与查阅资料得到如下体会;

1.        引用与取地址  (reference and address)  引用的&前面一定有类型符号,否则就不是引用, 取地址的&后面一定有变量名称,一旦出现&,一定把此搞明白

 int b =10, int &a,  这明显就是引用,&b 这就是取地址, test1(int &a, int &b) 这些是引用用在定义函数的时候, test4(&a, &b) 这个时候是取地址,&后面必须是变量名字,不能是其它的,比如&*b是不容许的,

2.       引用是变量的别名,与变量有相同的地址和值, & 只在定义的时候出现,以后不用出现, int &a =b,   以后直接在使用的时候用a 代表b, 不是用&a 代表b (单独出现&a,此时就是应用的地址了, 它就是b的地址)  &a==&b,地址是相等的。函数中如传递变量,  f(b), 如需要传递变量的地址f(&b)

3.     一个变量(包括指针)包括三个部分, 变量名字, 变量的值, 变量的地址,内存中地址是唯一的, 生命周期内名字和地址是关联的,多个名字可关联一个地址,值是地址上的储存内容,可以变的,名字没有直接和值关联,名字关联地址,地址在关联值, 这三个是三回事,地址和引用,地址,解引用就是解决此三部分不同的问题。

     一般的赋值等是对变量的值赋值,而不是地址等其他的, int b=10, 是b的值赋为10, 而不是地址 int *f , f=&b, 这是把指针的值赋为b的地址,而指针f本省的地址没有涉及

4.     指针与解引用 (pointer and dereference)  指针的*前面一定有类型符号,否则就不是指针, 解引用的*后面一定要有地址(指针或相当于值是地址的变量)一旦出现×,一定高明,  int * f, 只是指针定义, 而如果单独出现 *f 这个时候是解引用,  test8(int ×a, int ×b) 这些是指针用在定义函数的时候, test9(×a, ×b) 这个时候是解引用,传递的指针对应的解引用, ×&f  这个就是变量f的地址的解引用,就是变量f的值

5 . 指针里面的值是变量的地址, × 只在定义的时候出现,以后不出现, int*f,   f=&b,  以后直接用f 代表 &b, 用*f(解引用)代表b, 代表是可以写等于的意思。而不是以后也用*f=&b, f=b.

6. 指针就是变量本身储存的值是另一个变量的地址, 和它本身的地址是两回事, 解引用是指针的值(地址)作为另一个变量的地址, 这个地址对应的值。int *f =&b, 

此时f的地址是:HHH, f的值是AAA,  b的地址是AAA, b的值是CCC,  HHH 就是&f, ×f 就是CCC。二级指针就是指向指针的指针,相当于这里的CCC又是一个变量的地址, 

7. 作为参数传递等的时候,一定要抛开类新定义时前两*或&的符号,左边的值与右边建立对等关系 ,左边值是地址,右边就是地址,左边值是值, 右边也就是普通的值,  如 fee(int* f), int k,  在实参引用的时候要fee(&h), 不能fee(h), 因为定义中*是类型符号,f的值是地址, 要与&h才一直,  fee(int &h) , int k,  在实参引用的时候要fee(k). 因为&是类型符,h是引用,值和变量一样, 而不能是地址参数fee(&h)

8.  引用不分配内存, 而指针分配, int d, int& f=d,, int *u =&d , 此时d和f 的值, 地址一模一样,u的值和d的地址上一样, u有它自己的地址。

9. 作为参数传递,指针作为参数的时候是临时拷贝一个副本( 不同的地址),它的值和原来的指针一样,及指向的地址和原来的指针指向的一样,他们有相同的解引用,因此对函数内这个临时指针的值的操作都不会影响到原来的指针,只是把临时指针的值变了,及指的地址变了,如果不对这个临时指针操作,而对它的解引用操作, 由于和原来的指针指向同一个地址,有相同的解引用,因此对临时指针的解引用操作会影响到原来的解引用,要在函数退出后而使原来的值的变化有保留,就必须把要改变的值放在传递指针的解引用里面。 要想让指针作为参数在函数中操作完后有变化有保留,因此要让产生的临时指针指向这个指针的地址,临时指针的解引用就是这个指针,临时指针的解引用变化,这个指针的值就变化,这个指针的解引用,和临时指针的解引用的解引用一致,就是二级指针或双指针。及指针用作参数传出时需要二级指针。

int *a=&b, 

int c*=&d,   

exchange(int*f, int*e),  

{

  int * temp 

temp =f;

f=e,

e=temp

}

exchange(a, c)

执行时; 

f 是一个临时指针指向b的地址, *f就是b    函数外a 指向b的地址

e是一个临时指针指向d的地址, *e就是d   函数外c指向d的地址

交换后

f 是一个临时指针指向d的地址, *f就是d    函数外a 指向b的地址

e是一个临时指针指向b的地址, *e就是b   函数外c指向d的地址

因此函数内部变了,外部没有变, 退出后还是原样子。

如果是

exchange(int*f, int*e),  

{

  int  temp 

temp =*f;

*f=*e,

*e=temp

}


exchange(a, c)


此时执行

f 是一个临时指针指向b的地址, *f就是b    函数外a 指向b的地址 *a就是b

e是一个临时指针指向d的地址, *e就是d   函数外c指向d的地址  *c就是d

交换后

f 是一个临时指针指向b的地址, *f就是d    函数外a 指向b的地址 *a就是b   但此时 b的值变成d的值了,  b的名称和地址没有变

e是一个临时指针指向d的地址, *e就是b   函数外c指向d的地址  *c就是d   但此时 d的值变成b的值了      d的名称和地址没有变

如前名称和地址是绑定的, 这次是把值变了


如果是

exchange(int**f, int**e),  

{

  int * temp 

temp =*f;

*f=*e,

*e=temp

}


exchange(&a, &c)  注意此时格式

执行时 


f 是一个临时指针指向指针a的地址, *f就是a,    * a就是b, **f就是 b,   函数外a 指向b的地址 *a就是b

e是一个临时指针指向指针c的地址, *e就是c    *c就是d, **e就是 d     函数外c指向d的地址  *c就是d

执行后

f 是一个临时指针指向指针a的地址, *f就是a, 此时a的名称和地址没有变,但值变成了c的值   * a就指向* c 即 d, **f就是 d,   函数外a 指向d的地址 *a就是d

e是一个临时指针指向指针c的地址, *e就是c  此时c的名称和地址没有变, 但值变成a的值,  *c就指向*a  即 b, **e就是 b     函数外c指向d的地址  *c就是b

这样的操作是在指针的值的层面上做了交换,上面一种是在原数据基础上做了交换。 

10. 引用作为参数,是直接把实参的地址和值当作引用的,起了个别名,相当于给这段地址关联了一个名字,相比指针少了一个临时的指针的地址。因此函数内部对别名的操作就相当于对原实参操作。

exchange(int &f, int &e),  

{

  int  temp 

temp =f;

f=e,

e=temp

}

exchange(b, d)

执行时
f 的值是b, f的地址是b 的地址

e的值是d, e的地址是 d 的地址

执行后

 f的值是c的值, f 的地址还是原来b的地址 b的地址中变成c的值了

e的值变为d的值, e的地址还是原来b的地址, c的地址中变成b的值了,

在数值层面上交换了。

11. 引用和指针相结合,产生了指针类型的引用 int *&f  它的意思是f和一个指针有相同的地址和值。

exchange(int *&f, int *&e),  

{

  int  temp 

temp =f;

f=e,

e=temp

}

exchange(a, c)  注意里面一定要指针

执行时   f  就相当于指针  a

e 就相当于指针c, 

 这样相当于把外面指针直接拿到函数内使用了。 比刚才二级指针效率提升了许多。

引申 

一般的情况是

            二级指针——> 一级指针—->原数据

 要想原数据改变有多种方式

           直接改变 

           利用一级指针做中介 改变一级指针的解引用

           利用二级指针做中介,改变二级指针的解引用, 此时绑定一级指针值和原数据,

           使用指针作为中介的地方都可直接使用引用。去掉中介。


————-










原创粉丝点击