2025年08月05日
帐号 密码


探究向函数传函数指针的方法

文章作者:cdeng

  首先,与int *型变量对比,说明函数指针变量的定义方法:
    int a;        整型变量a
    int *a;        整型指针变量a
    int a(char , char )       函数a,函数类型为:返回值为int,参数为char,char。
    int (*a) (char , char )    返回值为int,参数为char,char的函数的函数指针变量a。

  初步了解了函数指针的定义方法,值得注意的是int(*)(char,char)就和int *类似,可以用来对变量进行强制转化,转化为函数指针类型的变量,它不是说可以不写函数指针的变量名来定义。下面接着对两个程序进行研究。

  先看第一个程序:
  int f(char,char);

  main()
  {
   int a;
   int b;
   long c;
   int (*p)(char,char);

   p=f;
   b=(int)f;
   c=(long)f;
 
   printf("main=%x f=%x\n",main,f);
   printf("p=%x b=%x c=%lx\n",p,b,c);

   a=p(1,2);
   printf("%d\n",a);

   a=((int (*)(char,char))b)(1,2);
   printf("%d\n",a);
  }

  int f(char a,char b){return a+b;}

  这个程序的打印结果如下:
    图 

  从第一行打印结果可以看到函数名的值是它的入口地址;从第二行打印结果可以看到函数指针p和整型变量b的值变为了函数名的入口偏移地址,长整型c的值变为了函数名的入口地址,段地址是CS;第三行和第四行的打印结果是一样的,都是函数f在传1和2的参数以后的返回值,可以看到我们成功的使用函数指针p和强制转化为函数指针的变量b完成了在调用函数f()时f的作用,这个地方p,b和f的值都是一样的,都是函数f的入口地址,p和b其实是一样的,都是作为函数指针来使用的。说明整型变量可以用来调用返回值不是far型的函数,当然得进行强制类型的转化,这样就可以省去定义函数指针,不过还得进行强制类型的转化。f的值是不可以改变的,那么它可能就是一个函数指针常量,定义一个函数指针常量p1,做如下测试:
  1.分别利用p和p1调用函数p,并进行输出,看结果是否一样    (一样)
  2.分别将p和p1取一次*,并输出结果,看结果是否一样        (一样)
  3.分别将p和p1取一次&,并输出结果,看是否都不出错        (都不出错)
  4.分别将p和p1取多次*,并输出结果,看结果是否一样        (一样)
  5.分别将p和p1取两次&,看是否会出错                (都出错)
  括号里是我做这些测试得到的结果,那么可以确定函数名其实就是一个函数指针常量。那么函数指针的一个作用也就出来了,那就是灵活的指向不同的函数,从而对不同的函数进行灵活的调用,相当于该函数的一个别名,而且它可以不停的改变,成为不同的函数的别名,但是这个作用带来了什么方便之处,我还是一头雾水。下面先继续对第二个程序进行研究。
  int far f(char,char);

  main()
  {
   int a;
   int b;
   long c;
   int (far *p)(char,char);

   p=f;
   b=(int)f;
   c=(long)f;
 
   printf("main offset=%x\n",main);
   printf("main=%lx\n\n",(long)main);
   printf("f offset=%x\n",(int)f);
   printf("f=%lx\n\n",f);
   printf("p=%lx b=%x c=%lx\n",p,b,c);

   a=p(1,2);
   printf("%d\n",a);

   a=((int (far *)(char,char))c)(1,2);
   printf("%d\n",a);
  }

  int far f(char a,char b){return a+b;}

  第二个程序的运行结果如下
  图 

 
  这个程序和第一个类似,一样的就不说了,不一样的就是对于返回值是far型的函数,不想定义该类型的函数指针时,可以定义一个长整型变量,把值赋为函数的入口地址值,然后向调用该函数的时候可以把该变量强制转化为函数指针,从而对该函数进行调用。同样的做是可以这样做,但好像这样反而增大的调用函数的难度。不明白它的真正实际作用到底是什么。
  我写的描述函数指针数组用法的程序如下:
  int f(char,char);
  int g(char,char);

  main()
  {
    int (*a[2])(char,char),b;
    a[0] = f;
    a[1] = g;
    b = a[0](1,2);
    printf("%d\n",b);
    b = a[1](1,2);
    printf("%d",b);
  }

  int f(char a,char b)
  {
    return a+b;
  }
  int g(char a,char b)
  {
    return a-b;
  }
  这个程序的思想就是有多个名称不同但是参数类型和个数都相同的函数,这时候用一个函数指针就不够用了,需要多个函数指针,而这种情况下这些函数指针的定义方式和类型是相同的,那么就可以用数组来简化这个定义过程,有几个这样的函数,我们就把数组长度设置为几,这样函数指针数组的每一个数都得到了充分的利用,而且简化了定义过程。数组中的每一个函数指针都是独立的,都和定义一个函数指针的作用是一样的。这个是类似于基本类型的各种变量数组的。
  
  向函数传函数指针的方法我想到两种,下面进行分别介绍:
  第一种方法是受书上的两个程序启发想到的,既然我们可以把一个函数名的值传递给一个整型变量,然后把整型变量强制转化为函数指针来使用。那么我们是不是可以在传递函数指针时,把函数指针强制转化为整型来传递,然后在函数中再把整型强制转化为函数指针来使用。因为函数指针的值就是函数的入口地址,把函数指针强制转为相应的整型或者长整型(不是far型的转化为整型,far型的转化为长整型),值是不会改变的,这还是有一定的可行性的,进行验证这个方法确实可行,验证程序  代码如下:
  int f(int,char,char);
  int g(char,char);

  main()
  {
    int (*p)(char,char),a;
    p = g;
    a = f((int)p,1,2);
    printf("%d",a);
  }

  int f(int a,char b,char c)
  {
    return ((int (*)(char,char))a)(b,c);
  }

  int g(char a,char b)
  {
    return a-b;
  }
  这个程序就是把一个int (*)(char,char)类型的函数指针强制转化为一个整型,传递给函数f,然后在函数f中又把这个整型强制转化为一个函数指针来调用函数g,结果运行结果如下:
  图 

 
  和预想的一样,说明这个方法是可行的,对于far型的函数,用long型的变量就可以了。
  第二种方法是直接传递函数指针,程序代码如下:
  int f(int (*p)(char,char),char,char);
  int g(char,char);

  main()
  {
    int (*p)(char,char),a;
    p = g;
    a = f(p,1,2);
    printf("%d",a);
  }

  int f(int (*p)(char,char),char b,char c)
  {
    return p(b,c);
  }

  int g(char a,char b)
  {
    return a-b;
  }
  这个程序就是在函数f中弄一个int(*)(char,char)的形参来接收该类型的函数指针,然后传递这样一个实参,调用该函数,结果打印如下:
  图 

 
  和预想的一样,说明这个方法也是可以的。
  至于函数的一些其他特点我做了一下研究:输出一下各种类型的函数指针的大小,结果发现它和其它基本类型的指针的大小是一样的,都是两个字节。
定义一个函数指针p,然后对p进行运算,比如自加或者加一个数值,发现函数指针是不可以进行运算的。对p进行赋值,把一个函数的地址给p,然后再对p进行运算,结果还是不可以。也就是说函数指针是不可以进行运算的。

发表日期:2012年07月07日

网友评论(0)

当前1/1页 首页 上一页下一页 尾页

我也跟评:

     验证码 验证码... [看不清]