关于C++指向指针的指针的一点测试与理解

这几天看C++的指针,刚开始的时候还算清楚,看到指向指针的指针这一块的时候就不淡定了。现假设p为指向指针的指针,看看下面的一堆东西。

p &p *p (void *)*p **p *p+1 *(p+1) **p+1 **(p+1) 这些东西都代表啥意思呢?输出是怎样的?为什么会这样?做个试验看看吧。

试验代码如下:

#include<iostream>
using namespace std;
int main(){
	char *test[]={"my","name","is","sunnix"};//声明一个指针数组
	char **p=test;//声明一个指向指针的指针
	cout<<"p="<<"\t"<<p<<endl
		<<"&p="<<"\t"<<&p<<endl
		<<"*p="<<"\t"<<*p<<endl
		<<"(void *)*p="<<"\t"<<(void *)*p<<endl
		<<"**p="<<"\t"<<**p<<endl
		<<"*p+1="<<"\t"<<*p+1<<endl
		<<"*(p+1)="<<"\t"<<*(p+1)<<endl
		<<"**p+1="<<"\t"<<**p+1<<endl
		<<"**(p+1)="<<"\t"<<**(p+1)<<endl;

}
先看看输出结果:

这个时候就应该问问为什么了。

第一句非常好理解,p为指向指针的指针,不管他指向什么,说到底还是指针,那么他当中存放的就是地址,只不过这个地址是另一个指针的地址。在本例当中这个另一个指针就是指向字符串“my”首地址的指针。

第二句也非常好理解,p当中不管保存的是什么,本身是要占用内存的,“&”为地址运算符,那么&p就是p本身在内存当中的地址。

第三句很奇怪,p是一个指向指针的指针,那么“*”为间接引用运算符,返回的是指针所指向的对象,本例中他指向一个指针,那么取出的不应该是p所指向的指针中保存的地址么?我的理解是这样的,p为指向指针的指针,*p取出的是他所指向的指针中保存的地址,在本例当中这个地址就是下一句输出的地址01027894,系统取到这个地址以后,发现这个地址中保存的是字符型的,所以cout会输出这些字符,直到遇到‘\0’结束输出,所以本例当中输出了“my”。

第四句,将*p的类型进行强制转换,转成通用型的指针类型,这时候输出的是这个指针所指向的地址。

第五句,p是一个指向指针的指针,那么p指向一个指针,进行*p运算以后,*p就不再指向一个指针,而是指向一个具体的对象,**p就相当于*(*p)运算,这时,返回的就是*p所指向的具体的对象。在本例当中,指向的就是m这个字符。我自己理解的p、*p和**p的区别。p和*p都是指针,而**p是*p所指向的具体的对象。输出时p和*p都表示的是一个地址,只不过*p所指向的地址保存的是字符串,cout语句会将这些字符串输出,直到遇到‘\0’结束符。

第六句,*p+1由于“*”的优先级高于“+”,所以先进行*p运算,*p依然是一个指针,指向字符串“my”的首地址,“+1”运算以后就指向了“y”,此时会将“y”后面的字符串输出,只是本例中“y”已经结束,所以只输出了“y”,假设“y”后面还有字符串“abc”,那么输出就是“yabc”。

第七句,*(p+1)因为"()"优先级高于"*",先进行p+1运算,p+1同样为一个指向指针的指针,+1运算完成后会指向下一个指针,再进行“*”运算以后,指向这个指针指向的对象,本例中指向了“name”的首地址,然后输出“name”。“*p+1”和“*(p+1)”的区别就在于前者先取对象,再移动指针。后者先移动指针,再取指针所指的对象。因为p指向一个指针数组,所以后者的操作是合法的。

第八句,**p+1,**P已经不是一个指针,而是一个具体的对象,本例中为字母“m”,再进行“+1”运算,是将字母“m”的ASCII值和1相加,所以得到110。

第九句,**(p+1),此时先进行指针的移动运算,移动后*(p+1)指向了“name”的首地址,再进行**(p+1)运算,取出这个首地址中的对象,即字符“n”,进行输出。

最后,水平有限,有理解不到位的地方欢迎指出,说法不正确或者不专业的地方也欢迎指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
指向类的成员的指针C++中,可以说明指向类的数据成员和成员函数的指针指向数据成员的指针格式如下: ::* 指向成员函数的指针格式如下: (::*)() 例如,设有如下一个类A: class A { public: int fun (int b) { return a*c+b; } A(int i) { a=i; } int c; private: int a; }; 定义一个指向类A的数据成员c的指针pc,其格式如下: int A:: *pc = &A::c; 再定义一个指向类A的成员函数fun的指针pfun,其格式如下: int (A:: *pfun)(int) = A::fun; 由于类不是运行时存在的对象。因此,在使用这类指针时,需要首先指定A类的一个对象,然后,通过对象来引用指针指向的成员。例如,给pc指针指向的数据成员c赋值8,可以表示如下: A a; a.*pc = 8; 其中,运算符.*是用来对指向类成员的指针来操作该类的对象的。 如果使用指向对象的指针来对指向类成员的指针进行操作时,使用运算符->*。例如: A *p = &a; //a是类A的一个对象,p是指向对象a的指针。 p ->* pc = 8; 让我们再看看指向一般函数的指针的定义格式: *() 关于给指向函数的指针赋值的格式如下: = 关于在程序中,使用指向函数的指针调用函数的格式如下: (*)() 如果是指向类的成员函数的指针还应加上相应的对象名和对象成员运算符。 下面给出一个使用指向类成员指针的例子: #include class A { public: A(int i) { a=i; } int fun(int b) { return a*c+b; } int c; private: int a; }; void main() { A x(8); //定义类A的一个对象x int A::*pc; //定义一个指向类数据成员的指针pc pc=&A::c; //给指针pc赋值 x.*pc=3; //用指针方式给类成员c赋值为3 int (A::*pfun)(int); //定义一个指向类成员函数的指针pfun pfun=A::fun; //给指针pfun赋值 A *p=&x; //定义一个对象指针p,并赋初值为x cout<*pfun)(5)<<endl; //用对象指针调用指向类成员函数指针pfun指向的函数 } 以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。 对象指针和对象引用作函数的参数 1. 对象指针作函数的参数 使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针作函数参数有如下两点好处: (1) 实现传址调用。可在被调用函数中改变调用函数的参数对象的值,实现函数之间的信息传递。 (2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少时空开销。 当形参是指向对象指针时,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针作函数参数。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M *m); void setxy(int i, int j) { x=i; y=j; } void print() {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值