36-函数与指针分析

注:博客中内容主要来自《狄泰软件学院》,博客仅当私人笔记使用。

测试环境:Ubuntu 10.10

GCC版本:4.4.5

 

一、函数类型

1) C语言中的函数有自己特定的类型

2) 函数的类型由返回值参数类型参数个数共同决定

                   int add(int i,int j)的类型为int (int,int)

3) C语言中通过typedef为函数类型重命名

                   typedef type name(parameter list)

例:

                   typedef int f(int,int);

                   typedef void p(int);

 

二、函数指针

1) 函数指针用于指向一个函数

2) 函数名是执行函数体的入口地址

3) 可通过函数类型定义函数指针:FuncTypepointer;

4) 也可以直接定义:type (*pointer)(parameter list);

         -  pointer为函数指针变量名

         -  type为所指函数的返回值类型

         -  parameter list为所指函数的参数类型列表

 

三、面试小问题

         如何使用C语言直接跳转某个固定的地址开始执行?

                通过函数指针,跳转到函数开始执行。

实例分析
函数指针的使用
36-1.c
 
#include <stdio.h>
 
typedef int(FUNC)(int);    //重命名函数类型为FUNC
 
int test(int i)     //函数模型和FUNC相同
{
    return i * i;
}
 
void f()
{
    printf("Call f()...\n");
}
 
int main()
{
   FUNC* pt = test;
   void(*pf)() = &f;     //函数取不取地址都代表函数名,这样为了兼容老式编译器
 
   printf("pf = %p\n", pf);
   printf("f = %p\n", f);
   printf("&f = %p\n", &f);
   
   pf();      //函数调用,等价于调用f()。当代编译器都支持
   
   (*pf)();   //函数调用。等价于f()。早期的嵌入式编译器支持
   
   printf("Function pointer call: %d\n", pt(2));    //4
   
   return 0;
}

操作:

1) gcc 36-1.c -o 36-1.out编译正确,打印结果:

pf = 0x8048459
f = 0x8048459
&f = 0x8048459
Call f()...
Call f()...
Function pointer call: 4

2) 直接使用函数地址赋值给函数指针:

int main()
{
   FUNC* pt = test;
   //void(*pf)() = &f;     //函数取不取地址都代表函数名,这样为了兼容老式编译器

   void(*pf)() = 0x8048459;
   
 
   printf("pf = %p\n", pf);
   printf("f = %p\n", f);
   printf("&f = %p\n", &f);
   
   pf();      //函数调用,等价于调用f()。当代编译器都支持
   
   (*pf)();   //函数调用。等价于f()。早期的嵌入式编译器支持
   
   printf("Function pointer call: %d\n", pt(2));    //4
   
   return 0;
}

编译有警告:

36-1.c:19:17: warning: initialization makes pointer from integer without a cast [enabled by default]
  void (*pf)() = 0x8048459;
                 ^
警告:用整数初始化指针

打印结果:

pf = 0x8048459
f = 0x8048459
&f = 0x8048459
Call f()...
Call f()...
Function pointer call: 4

 

四、回调函数

1) 回调函数是利用函数指针实现的一种调用机制

2) 回调机制原理(对比函数调用理解:函数调用就固定了功能)

         - 调用者不知道具体事件发生时需要调用的具体函数

         - 被调函数不知道何时被调用,只知道需要完成的任务

         - 当具体事件发生时,调用者通过函数指针调用具体函数(使用方式)

3) 回调机制中的调用者和被调函数互不依赖

实例分析
回调函数使用示例
36-2.c
#include <stdio.h>
 
typedef int(*Weapon)(int);    //定义函数指针
 
void fight(Weapon wp, int arg)
{
    int result = 0;
   
    printf("Fight boss!\n");
   
    result = wp(arg);    //(重点)打算用函数调用替换,但是函数调用就必须固定某个函数!!回调就不确定了!
    
    printf("Boss loss: %d\n", result);
}
 
int knife(int n)
{
    int ret = 0;
    int i = 0;
   
    for(i=0; i<n; i++)
    {
       printf("Knife attack: %d\n", 1);
       ret++;
    }
   
    return ret;
}
 
int sword(int n)
{
    int ret = 0;
    int i = 0;
   
    for(i=0; i<n; i++)
    {
       printf("Sword attack: %d\n", 5);
       ret += 5;
    }
   
    return ret;
}
 
int gun(int n)
{
    int ret = 0;
    int i = 0;
   
    for(i=0; i<n; i++)
    {
       printf("Gun attack: %d\n", 10);
       ret += 10;
    }
   
    return ret;
}
 
int main()
{
    fight(knife, 3);
    fight(sword, 4);
    fight(gun, 5);
   
    return 0;
}

操作:

1) gcc 36-2.c -o 36-2.out编译正确,打印结果:

Fight boss!
Knife attack: 1
Knife attack: 1
Knife attack: 1
Boss loss: 3
Fight boss!
Knife attack: 5
Knife attack: 5
Knife attack: 5
Knife attack: 5
Boss loss: 20
Fight boss!
Knife attack: 10
Knife attack: 10
Knife attack: 10
Knife attack: 10
Knife attack: 10
Boss loss: 50

小结:

1) C语言中的函数都有特定的类型

2) 可以使用函数类型定义函数指针

3) 函数指针是实现回调机制的关键技术

4) 通过函数指针可以在C程序中实现固定地址跳转

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值