c语言最大的两个数指针专题,c语言中的指针专题(2)

int *p1=&i;

int**p2=&p1;

综合以上的所有点,下面是我们常常看到一些匹配(也是经常出错的地方):

int a[3],b[2][3],c,*d[3]; void fun1(int *p); void fun2(int

(*p)[3]); void fun3(int **p); void fun4(int p[3]); void fun5(int

p[]); void fun6(int p[2][3]); void fun7(int (&p)[3]);

函数 不会产生编译时刻的可能值(但逻辑上不一定都对)

函数

不会产生编译时刻的可能值(但逻辑上不一定都对)

fun1

a, &a[i], *b

,b[i],&b[i][j] ,&c ,d[i]

fun2

b,b+i,

fun3

d

fun4

a, &a[i], *b

,b[i],&b[i][j] ,&c ,d[i]

fun5

a, &a[i], *b

,b[i],&b[i][j] ,&c ,d[i]

fun6

b

fun7

a

为什么可以有这样的搭配,原因如下:

对于fun1 fun4 fun 5:

在编译器看来fun1,fun4,fun5的声明是一样,在编译时候,编译器把数组的大小舍去不考虑,只考虑它是一个指针,也就是说有没有大小说明是一样的,所以三者的形式都是fun1的形式(其实只要提供了int*指针就可以了);

对于fun7

:以上的解释对于引用是不适用的,如果变量被声明为数组的引用,那么编译器就要考虑数组的大小了,那么必须和声明一模一样(所以fun7就只有a合适);

对于fun2:p是一个指向一个含有3个元素的数组,这样b和b+i正好合适,而a却不是(它是指向a[0]的,不是指向这个数组的);

对于fun3:p是一个指针的指针,而d指向d[0],同时d[0]又是一个指针,所以d就是一个指针的指针。但是b却不是(它是一个2*3的矩阵也就是年int

[2][3]类型);

对于fun6,p是一个2*3的数组类型,和b恰好完全匹配;

二、函数指针、函数的指针参数以及返回指针的函数

A) 函数指针

C++规定,一个函数的地址就是这个函数的名字。我们需要指出的就是一个指针需要指定类型是为了后来的指针解析时候使用,通过指针有效快速访问对象。那么对于函数的指针,它要表示出该函数的那些特性才能满足解析的唯一性呢?答案就是一个函数的特性有它的参数列表和返回类型。

下面是一个函数指针的例子:

int (*p)(int I,int j);

不能是

int *p(int I,int j),

这样就变成了返回指针的函数声明了。

在C++中处于对安全性的考虑,指针和它指向的对象要类型一致,也就说上面的指针所指向的函数的特性要和它一模一样:例如指向int

min(int I,int j);是可以的。但是指向int min(double I ,double

j);是不可以。函数指针也和其他的指针一样,在使用的时候很怕发生"悬空",所以在使用的时候同样要判断有效性,或者在定义的时候就初始化。

int (*p)(int I,int j)=min; int (*p)(int I,int j)=&min;

int (*p)(int I,int j)=0;

B) 函数的指针参数

函数指针可以作函数的参数:例如我们有一个积分的算法,对于不同的数学函数可以进行积分(我们这里假设函数都是一元的);

那么我们的算法接口可以定义为:

templateT integrate( T lower, T upper , T (*)(T)=0

)throw(integrated_exp);

这里的最后的参数是一个函数的指针,并且被设定缺省值为0。这个函数返回一个值,同时需要一个参数。假如加入我们有这样的一个函数:

double line(double x){ return a*x+b;}

那么我就可以使用了。

函数指针还可以作为返回类型(注意不是函数!!,某个特定的函数是不可以作为返回类型的。)假设:

typedef int (*PF)(int ); PF getProcessMethod( );//true

C) 返回指针的函数

一个函数的返回是函数的重要接口之一,c++的一个重要的强大的功能就是能够设计足够复杂和好用的用户自定义类型。而同时处理和传递这些类型也是很麻烦的一件事情,我们不想把我们的时间都花在这些对于我们的实际工作没有很实质帮助的拷贝上,解决这个问题就要依赖我们的接口设计:c和c++都提供了相应的解决方案,在c++中我们可是使用引用,讲他们作为函数的实际参数,或者我们在函数的实际参数中使用一个指针等。同样我们还可以使用一个函数返回一个指针:但是这是一个很不好解决的问题!

我们首先容易出错的是:将一个局部变量的地址传出来!例如:

UserType * Process( ) {   UserType ut(param-list);

//process ut;   return &ut;// }

这个变量在我们的函数结束的时候就被销毁了,尽管地址可以传出去,但是这个地址已经不存在了,已经不能使用的东西,在这个函数之外却不知道,难免要出错!

同时我还会有一个比较麻烦的问题:使用new,又容易造成内存泄露

UserType * Process ( ) {   UserTpye *put=new

UserType(param-list );   //process put;   return put; }

我们在函数内部使用了一个new,分配了一个空间,这样传出来也是可以!

就是说不会发生上面的问题了。但是用户通常都会忘记在程序的外面在把这个借来的空间还回去!内存空间就这样泄露了!

可能也是这些另人无奈的问题,所以很多程序员把函数的参数设定为指针或者引用,以此来代替这种向外传输吧!总之,使用这种返回指针的函数要小心!

三、类成员的指针

类成员和一般的外部变量相互比较,不同就是它所在的域不同,这个域很重要,它决定了该变量可以使用的范围。那么一个指针如果要指向类的成员函数或者成员变量,那么除了要表达它的返回类型、参数列表或者类型之外,那么还要说明它所指向的变量(或者函数)的域,为了说明该域我们要使用类域限定:

class NJUPT {   static double money=20000000;   int num;

public:   NJUPT():num(10){};   int get(){return num;};

double getMoney(){reuturn money;} }

我们定义成员的指针为

int NJUPT:: *p;//指向int型成员变量 int (NJUPt::*)p()//指向int

f()型成员函数。

为了使用这些指针,我们需要使用该类型的变量或者指针。

NJUPT s,*ps;

那么调用的方式为:

cout<<*p)();

这个看起来似乎很奇怪!但是只要你想到我们定义的指针被限定在了类域中了(我们在开始定义的使用使用了NJUPT::

),这么使用也是很自然的。

如果一个类还有一些静态成员变量和静态成员函数,那么我是否也想这样使用呢?

答案是不用,静态成员我们就可以象使用外部的普通成员一样定义一个指针或者函数指针来访问就可以了,究其原因主要是这个成员的类型性质决定的。

double *p=&NJUPT::money; double

(*p)()=&NJUPT::getMoney():

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值