首页 > 技术文章 > C语言-指针

kernelx 2021-05-29 01:02 原文

复杂函数指针

Think in C++中介绍了一种复杂函数指针的分析方法

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

 

void (*funcPtr)();               // funcPtr 是一个函数指针,该指针指向的函数没有参数,没有返回值。

void *(*(*fp1)(int))[10];          // fp1 是一个指向函数的指针,该函数拥有一个int型的参数,返回值是一个指向拥有10元素的指针数组,数组中每个元素都是void * 类型。

float (*(*fp2)(int,int,float))(int);   // fp2 是一个指向函数的指针,该函数拥有三个参数,分别是int,int和float类型,返回一个指向函数的指针,该函数拥有一个int型的参数,返回值是float类型。

typedef double (*(*(*fp3)())[10])();   // fp3 是一个指向函数的指针,该函数没有参数,返回一个指向拥有十个元素的数组,数组的每个元素是一个函数,这10个函数都没有参数,返回值是double类型。

int (*(*f4())[10])();             // f4是一个函数,返回值是一个指向拥有10个元素的数组,每个数组元素是一个函数指针,这些指针指向的函数返回值为int类型。

 

 


 

  1 /**
  2  * main函数的参数    
  3  * main函数可以理解为操作系统调用的函数
  4  * 在执行程序的时候可以向main函数传递参数
  5  * int main()
  6  * int main(int argc)
  7  * int main(int argc, char *argv[])
  8  * int main(int argc, char *argv[], char *env[])
  9  * argc - 命令行参数个数
 10  * argv – 命令行参数数组
 11  * env  – 环境变量数组
 12  */
 13 
 14 
 15 /*普通指针*/
 16 int *p;
 17 
 18 
 19 /** 
 20  * 数组指针
 21  * 数组指针用于指向一个数组
 22  * 数组名是数组首元素的起始地址 , 但并不是数组的起始地址
 23  * 通过将取地址符& & 作用于数组名可以得到数组的起始地址
 24  * 可通过数组类型定义数组指针 : ArrayType* pointer;
 25  * 也可以直接定义 :type (*pointer)[n];
 26  * pointer    为数组指针变量名
 27  * type     为指向的数组的类型
 28  * n        为指向的数组的大小
 29  */
 30 int buf[6];
 31 
 32 //直接定义:
 33     int (*p)[n] = &buf;
 34     
 35 //数组类型重命名定义:
 36     typedef int(INT6)[6];
 37     INT6 *p1 = &buf;        //数组指针,sizeof(p1) = 6 * sizeof(int) = 24字节
 38     INT6 p2;                //数组。p2 == int p2[6]
 39 
 40     
 41 /**
 42  * 指针数组
 43  * 指针数组是一个普通的数组
 44  * 指针数组中每个元素为一个指针
 45  * 指针数组的定义 :type* pArray[n];
 46  * type*    为数组中每个元素的类型
 47  * pArray    为数组名
 48  * n        数组的大小
 49  */
 50 int *p[n];
 51 
 52 
 53 /**
 54  * 函数指针
 55  * 函数指针用于指向一个函数
 56  * 函数名是执行函数体的入口地址
 57  * 可通过函数类型定义函数指针 : FuncType* pointer;
 58  * 也可以直接定义 :type (*pointer)(parameter list);
 59  * pointer 为函数指针变量名
 60  * type 为指向函数的返回值类型
 61  * parameter list 为指向函数的参数类型列表
 62  */
 63 //直接定义:
 64     int (*p)(void);
 65     
 66 //数组类型重命名定义:
 67     typedef int(*HSZZ)(void);
 68     HSZZ hszz;
 69 
 70 
 71 /************************************************************
 72 * 等价关系
 73 *
 74 * 数组参数                    等效的指针参数
 75 * 一维数组:float a[5]            指针: float *a
 76 * 指针数组: int* a[5]            指针的指针:int** a
 77 * 二维数组: char a[3][4]        数组的指针:char (*a)[4] 
 78 *============================================================    
 79 * a 和&a 的区别
 80 * char a[]={1, 2, 3, 4, 5};        
 81 * a为数组是数组首元素的地址
 82 * &a为整个数组的地址
 83 * a和&a的意义不同其区别在于指针运算
 84 *-----------------------------------------------------------*/
 85 a + 1 = (unsigned int)a + sizeof(*a)
 86 &a + 1 = (unsigned int)(&a) + sizeof(*&a) = (unsigned int)(&a) + sizeof(a)
 87 
 88 /*****************************************************************
 89 * 注意;当指针取变量地址时,指针必须要和变量类型一样,不然会提取到错误(注意:此
 90 * 处的错误并不是说里面的数据有错误,而是说提取的数据不是你想要的)数据,如果运气
 91 * 好点会直接发生段错误。
 92 *
 93 * 如果是改变变量的值时,指针类型比变量类型不同,用指针改变变量时,变量的值是未知的;
 94 * 运气好的话也会发生段错误,悲催点那就需要自己调试程序,排除错误咯。
 95 *
 96 * 温馨提醒:除非是特意而为的,否则最好不要这样!!!
 97 *
 98 * char 型指针                     *char         提取1字节数据
 99 * short 型指针                    *short        提取2字节数据
100 * int 型指针                        *int         提取4字节数据
101 * long 型指针(如果是8字节)            *long        提取8字节数据
102 * long long 型指针(如果是16字节)        *long long    提取16字节数据
103 ******************************************************************/

推荐阅读