声明:本博文内容主要都来自于《Linux C编程一站式学习》
1.指针数组和指向数组的指针
先看看 int * a[10] 和 int (*a)[10]之间的关系。
int *a[10] 表示的是a是一个数组,数组里面存储的是int * 指针,即该表达式的意思是一个指针数组,这个数组中的每个元素都是指向int型的指针;
int (*a)[10] 表示的是 a 是一个指针, int [10] 是一种类型,即a是指向有10个元素的的数组指针。 int *a[10]; int ** p = &a[0]; // 或者 int**p = a ;
从上面的例子可以看出后面两个表达式是等价的
- 函数指针
void say_hello(const char* str ) { printf(""); } int main() { void (*f)(const char*) = say_hello; f("hello world"); return 0 ; }
void (f)(const char) 声明了一个函数指针,该指针指向参数为 const char ,返回值为void 的函数类型。其中 say_hello恰好是这种类型的函数,将其地址赋给该指针。 Note: say_hello是一种函数类型,函数类型跟数组类型相似,做右值时可以自动转化成函数指针类型,因此可以直接赋给f; 也可以写成 void (f)(const char*) = &say_hello;其效果是一样的。 - 下面区分函数类型和函数指针类型
首先定义函数类型: typedef int F(void) ; 再申明该函数类型的变量: F f , g ;
上面的等同:
int f(void) int g(void)
如果再申明: F h(void) 就错误了! 函数可以返回void类型、标量类型、结构体或者联合体,但是不能返回函数类型。看下面一定义: F e(void) 申明的该函数是返回F一个函数指针,其中指针为标量,只有大小之分。 下面看一个函数指针: int (f)(void) 是定义了一个函数指针,我们可以将这个函数指针定义一个类型名叫做FP: typedef int (FP)(void) 假设这个有个函数地址,真好指向这种类型的某个函数,Ox12345678,我们强制转换成一个函数指针并且调用它,两种方式都是 正确的:
((FP)0x12345678)() (*(FP)0x12345678)()
上面不用类型名,直接用函数类型也可以实现强制转换:
((int (*)(void))0x12345678)() (*(int (*)(void))0x12345678)()
4.用函数指针实现函数的选择实现
double rect_real_part(struct complex_struct z) { return z.a; } double rect_img_part(struct complex_struct z) { return z.b; } double rect_magnitude(struct complex_struct z) { return sqrt(z.a * z.a + z.b * z.b); } double rect_angle(struct complex_struct z) { double PI = acos(-1.0); if (z.a > 0) return atan(z.b / z.a); else return atan(z.b / z.a) + PI; } double pol_real_part(struct complex_struct z) { return z.a * cos(z.b); } double pol_img_part(struct complex_struct z) { return z.a * sin(z.b); } double pol_magnitude(struct complex_struct z) { return z.a; } double pol_angle(struct complex_struct z) { return z.b; } double (*real_part_tbl[])(struct complex_struct) = { rect_real_part, pol_real_part }; double (*img_part_tbl[])(struct complex_struct) = { rect_img_part, pol_img_part }; double (*magnitude_tbl[])(struct complex_struct) = { rect_magnitude, pol_magnitude }; double (*angle_tbl[])(struct complex_struct) = { rect_angle, pol_angle }; #define real_part(z) real_part_tbl[z.t](z) #define img_part(z) img_part_tbl[z.t](z) #define magnitude(z) magnitude_tbl[z.t](z) #define angle(z) angle_tbl[z.t](z)
由上面的例子,根据条件实现选择功能,但是将每个功能都具体分配到每个函数中,每个函数实现其简单的功能。通过一个检索
信息来选择实现哪一个函数,使函数实现功能单一化,不会兼顾多种情况,是代码“高耦合,低内聚”,更好的重用原来的代码。
5.复杂声明的解析
在分析复杂声明时,通常要借助typedef把声明分解成几种基本的形式。
分析下面的例子 int ((fp)(void *))[10]
a.首先定义
typedef int (*T(void *))[10] ; T1 *fp;
b.即上面的式子可以写成 : T fp , 其中T应该是一个函数类型,参数是void ,返回值是T2类型 ;
typedef int (*T2)[10] ; typedef T2 T1(void*) ; T1 *fp;
c. T2和*及括号在一起,应该是个指针;
typedef int T3 [10]; typedef int (*T2)[10] ; typedef T2 T1(void*) ; T1 *fp;