大宝自习室

道路就在脚下

指针学习笔记-2

| 评论

声明:本博文内容主要都来自于《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 ;

从上面的例子可以看出后面两个表达式是等价的

  1. 函数指针
    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;其效果是一样的。
  2. 下面区分函数类型和函数指针类型

首先定义函数类型: 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;

评论