复杂指针声明具体实例

左右声明法则:

首先从最里面的圆括号(未定义的标识符)看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明

修正:
笔者要对这个法则进行一个小小的修正,应该是从未定义的标识符开始阅读,而不是从括号读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个。

链接:https://www.cnblogs.com/Lunais/p/5969181.html


 

int (*func)(int *p);
首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看
右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是 int。

 

#include <stdio.h>

int max( int *p )
{
 return 0;
}

int main ()
{
 int *k;
 int (*func)(int *p) = &max;
 func( k );

  return 0;
}


 

 

int (*func)(int *p, int (*f)(int*));
func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int *和int (*)(int*)这样的形参,返回值为

int类型。再来看一看func的形参int (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。

 

#include <stdio.h>

int max( int *p )
{
 return 0;
}

int test( int *pt, int (*f)(int*))
{
 return 0;
}

int main ()
{
 int *k;
 int (*func)(int *p, int (*f)(int*)) = &test;
 func( k, &max);

  return 0;
}


 

 

int (*(*func)(int *p))[5];
func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组

#include <stdio.h>

typedef int(*TYPE)[5];
TYPE fun( int *k )
{
int a[5];
TYPE p=&a;
return p;
}

int main ()
{
  //func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针
  //所指向的数组的元素是具有5个int元素的数组。
  int (*(*func)(int *p))[5] ;
  func = &fun;
  return 0;
}

 


int (*func[5])(int *p);
func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰 func的,而是修饰func[5]的,原因是[]运算符优先级

比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为

#include <stdio.h>

int max( int *p )
{
 return 0;
}

int main ()
{
  int (*func[5])(int *p);
  func[0] = &max;

  return 0;
}

 


double (* (* P1)[10] )( double k );//数组指针,第一个*说明数组中包含的是指针,往右是参数列表,说明数组中包含的是函数指针,这些函数没有参数,返回值类型是double

 

 

#include <stdio.h>

/* "*(*P2[10])()"用typedef分解及使用 */
typedef double ( * ppt )( double k );
typedef ppt (*p)[2];

double M( double k )
{
 return k;
}

double L( double k )
{
 return k + 1;
}

int main ()
{
 double (*mm)(double k);
 p  a;
 ppt arry[2] = { &M, &L };
 a = &arry ;
 mm = **a;//得到&M地址
 mm = *(*a+1) ;//得到&L的地址
 printf( "%f\n", mm(3.14));

 getchar();
    return 0;
}


最后看一个比较难点的例子:double  ( *(* (*fp3)( double(*u)(double k) ) )[1] )(  double k  );

对比:double (* (* P1) [1] )( double (*p) ( double k ) );

/*分析 double (* (* P1)[1] )( double (*p) ( double k ) ) :用左右法分析 :首先找到未知变量P1,往右看到第一个括号,往左看遇到第一个*,说明P1是一个指针。跳出第一个内部括号,首先与【】结合,因为【】优先级比*高,说明P1是一个数组指针。在往右看是第二个括号),然后往左看遇到第一个*,说明数组指针里面的元素是一个指针,什么类型的指针呢?跳出第二个括号,往右是参数列表,说明数组中包含的是函数指针,这些函数double (*p) ( double k )类型,返回值类型是double   */

使用typedef分解  double (* (* P1)[1] )( double (*p) ( double k ) );

第一步:typedef double ( * ppt )( double k );==> double (* (* P1)[10] )( ppt k );

第二部:typedef ppt (*p)[1];==> 此时如果定义一个变量 (p a;),那么a的类型将和P1的类型一致

 

使用typedef分解  double  ( *   (*    (*fp3)( double(*u)(double k) )   ) [1] )(  double k  );

/*   如果把 (*fp3)( double(*u)(double k) ) 替换成P1,那么将和上面举的例子相同  */

第一步:typedef p (*fp3)( ppt point );//返回类型是一个数组指针,所以p是一个数组指针类型

第二步:typedef ppt (*p)[1];//定义一个数组指针,数组指针所指向的数组具有“函数指针,指向形参为double,返回为double”的特征

第三步:typedef double ( * ppt )( double k );//定义一个函数指针,指向形参为double,返回为double的函数

贴上测试类型代码:

#include <stdio.h>

typedef double ( * ppt )( double k );
typedef ppt (*p)[1];//p的类型为 ppt (*)[1];
typedef p (*fp)( ppt point );//定义一个函数指针,参数也是一个函数指针

typedef double  ( *(* (*fp3)( double(*u)(double k) ) )[1] )(  double k  );

int main ()
{
    fp3 jj;
    fp qq;
    jj = qq;

    return 0;
}//没有报错,说明使用typedef分解正确

最后贴上使用实例,以帮助大家更详细的了解:

#include <stdio.h>

typedef double ( * ppt )( double k );
typedef ppt (*p)[1];//p的类型为 ppt (*)[1];
typedef p (*fp)( ppt point );//定义一个函数指针,参数也是一个函数指针

//跟前面一样,先找到变量名fp3(这里fp3其实是新类型名),往右看是圆括号,调转方向往左是*,说明fp3是一个指针;跳出圆括号,
//往右看是ppt类型的参数,说明fp3是一个函数指针,接着往左是*号,说明该函数的返回值是一个指针;跳出第二层圆括号,往右是[]运算符,
//说明函数的返回值是一个数组指针,接着往左是*号,说明数组中包含的是指针;跳出第三层圆括号,往右是参数列表,说明数组中包含的
//是函数指针,这些函数有一个double的形参,返回值类型是double。简言之,fp3是一个指向函数的指针,所指向的函数具有ppt类型参数返回double类型的值,
//且返回一个含有1个数组指针,并且该数组指针所指向的数组具有ppt类型并且步长一样的数组。
typedef double  ( *(* (*fp3)( double(*u)(double k) ) )[1] )(  double k  );

//typedef double *(*P2[10])();//指针数组,数组里面的元素是函数指针,指向没有参数返回值为double类型的函数
//typedef double (* (* P1)[10])();//数组指针,第一个*说明数组中包含的是指针,往右是参数列表,说明数组中包含的是函数指针,这些函数没有参数,返回值类型是double
/* 如果max函数的类型定义为 P2,则会报错,因为函数不允许反回数组
P1 max( int *k )
{
 P1 pt;
 return 0;
}*/

double test( double result )
{
 return result;
}

/* 参数point为指向ppt(返回值为double,参数为double类型的参数)类型的指针 */
p func( ppt point )
{
 ppt b[1] = { point } ;//创建一个ppt类型的数组,数组元素为ppt类型
 p point_b;//创建一个数组指针,用于指向ppt类型的数组,注意步长要一样
 point_b = &b;
 return point_b;
}

int main ()
{
// ppt本身就是函数指针,ppt*为指向函数指针的指针
//  ppt* point;
//  point = &test;//报错

 fp a;//定义一个fp类型的函数指针
 ppt point_test;//定义一个ppt类型的函数指针

 a = &func;//&操作符只是显示地说明了编译器隐式执行的任务,a = func也可以
 point_test = **a( &test );//*a( &test ),取得数组b的地址。**a( &test ),取得数组b里面的内容,即test的地址

 printf( "%f\n", point_test(3.14));
 getchar();

}

 

参考链接:

https://www.cnblogs.com/Lunais/p/5969181.html

https://blog.csdn.net/skywalker_leo/article/details/48622193

 

 

 

 

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值