在结构体中使用函数

//C语言技巧--在结构体中使用函数例子(定义一个指向函数的指针) .

#include <stdio.h>  
#include <malloc.h>  
#include <memory.h>  
#define DECLARATION int (*ptr)(int x,int y)  
#define DEFINITION(x,y) ptr(x,y)  
int sum(int x,int y)
{  
 printf("x:%d\n",x);
 printf("y:%d\n",y);

    return(x+y);  
}

typedef struct { 
        int r; 
    //    DECLARATION;  
  int (*ptr)(int x,int y);  
} mystr; 
void main() 

    int a,b,c; 
 
    scanf("%d,%d",&a,&b); 
     mystr stru;   
  stru.ptr=sum;  
  c=stru.ptr(a,b);  
     printf("a=%d,b=%d,sum=%d\n",a,b,c);
     
    /* mystr *stru1;   */
    /* stru1=(mystr *)malloc(sizeof(mystr));   */
    /* memset(stru1,0,sizeof(mystr));   */
    /* c=stru1->DEFINITION(a,b); */

 
  
    /* //c=stru->ptr(a,b);    */
    /* printf("a=%d,b=%d,sum=%d\n",a,b,c);   */
 /* memset(stru1,0,sizeof(mystr));   */
 /* free(stru1);  xz */
}  

保存文件到struct_fun.c

编译:gcc -g -o struct_fun struct_fun.c

运行: ./struct_fun

 

 

2、

函数指针作为结构体成员 - [C语言]

2011-05-05

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://cnmcu.blogbus.com/logs/125730496.html

       今天在看《C\C++快速进阶教程》,看到一个“函数指针作为结构体成员”的程序,功能近似C++中的类中的成员函数,用那样的一种方法可实现定义的结构变量具有了方法的特性。

       程序如下(下面的程序运行于WinTC):

#include "stdio.h"
struct aa
{
     int a;
     int( *fun)(int,int);
};
int add(int x,int y);
main()
{
    struct aa bb;
    int cc;
    printf("%x\t",add);
    bb.a=1000;
    bb.fun=add;
    cc=bb.fun(3,5);
    printf("%d\t",cc);
    printf("%x\t",bb.fun);
    getch();
}
int add(int x,int y)
{
    return x+y;
}

       刚开始一看,觉得很茫然,是前所未见呀,很多教科书上也没讲,于是上百度搜了下,还真有怎么回事。找到一些资料,觉得很不错,贴出来分享一下:

++++++++++++++++++++++++++++++++++++++++++++++++++++++

       函数指针作为结构体成员,实现函数注册 作者:admin 日期:2010-02-04
有时我们需要将函数作为结构体的成员,模拟C++类的情形,可应用于方法注册。
#include

struct a
{
    void (*func)(char *);
};

void hello(char *name)
{
    printf ("hello %s\n",name);
}

int main()
{
    struct a a1;
    a1.func = hello;
    a1.func("illusion");
    system("PAUSE");
    return 0;
}

 


   #############################################################################################################
 
标 题: 
阅读权限:公众公开私有好友公开 
文章类型:原创 转载 
文章关键词(选填):     从已有的关键词中选择 
文章摘要(选填):查看文章摘要  struct file_operations {int (*seek) (struct inode * ,struct file *, off_t ,int);int (*read) (struct inode * ,struct file *, char ,int);int (*readdir) (struct inode * ,struct file *, struct dirent * ,int);int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned longint (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);int (*fasync) (struct inode * ,struct file *,int); 确 定取 消
  
        

   文章正文:
  在C++中,我们很容易就可以实现函数重载,特别是类的同名方法(多态)。那么,在C语言中我们可以有类似的应用吗?
     呵呵,今天我找到了一种。
     下面先给出我的说明代码,再做解释:
//-----------------------------------------------------------//
#include
struct A
{
    void* (*fun)();
};
void myfun1()
{
    printf("this is fun()\n");
}
int myfun2(int a)
{
    printf("this is fun(%d)\n",a);
    return a;
}

char myfun3(int a)
{
    printf("this is fun(%c)\n",a);
    return a;
}
int main()
{
    struct A a;
    a.fun=myfun2;
    printf("AAA  %d\n",a.fun());
    printf("AAA1  %d\n",a.fun(4));
    printf("AAA2  %d\n",a.fun(43,"32423"));

    a.fun=myfun3;
    printf("AAA  %d\n",a.fun());
    printf("AAA1  %d\n",a.fun(4));
    printf("AAA2  %d\n",a.fun(43,"32423"));
    return 0;
}

//-----------------------------------------------------------//
在GCC4.0下编译运行的结果如下:
//-----------------------------------------------------------//
hill@hill-laptop:~/Desk/temp$ gcc test4.c
test4.c: 在函数 ‘main’ 中:
test4.c:25: 警告:从不兼容的指针类型赋值
test4.c:30: 警告:从不兼容的指针类型赋值
hill@hill-laptop:~/Desk/temp$ ./a.out
this is fun(-1208768727)
AAA  -1208768727
this is fun(4)
AAA1  4
this is fun(43)
AAA2  43
this is fun(
AAA  -11
this is fun()
AAA1  4
this is fun(+)
AAA2  43
hill@hill-laptop:~/Desk/temp$
//-----------------------------------------------------------//

现在分析一下上面的代码:
首先,这个程序的思路是想用一个结构体模拟一个类,通过函数指针来申明“类”方法,并模拟多态性。
        void* (*fun)();--------(1)
是一个函数指针,注意,这里不要写成
        void (*fun)();--------(2)
接下来写了两个函数
    void myfun1();
    int myfun2(int);
在接下来的main函数中,我们为A实例a的fun域赋值,这里我们直接赋值了myfun2,若上面方法申明中采用(2),那么将不能把myfun2赋值给fun,因为void*是可以指向任何类型的指针,那么当然可以指向int。这里又定义了myfun3就是为类看看void*是否能自动的转化为char类型了。
    另外要说明的一点就是,调用a.fun时我实验了几种调用方法,如程序中所示,它对行参没有任何要求,在本例中,由于传入的是myfun2(int),若不加任何参数调用a.fun(),那么输入的int将随机而定;若参数多于两个,则只有第一个参数有效,其余参数被呼略掉;若第一个参数与所传入的函数不匹配,则虽然可以通过编译,但结果一般会与期望的不同(错误)。
    那么,它是否是多态呢?显然不是的,多态是个运行时概念,若想在C里面用同名函数则必须如此利用函数指针,在使用不同的重载形式前必须给函数指针赋上相应的函数才行,在本例中,若要用重载型myfun3的话,在调用a.fun(...)前必须有这样一行
    a.fun=myfun3;
这是因为C毕竟还是一个静态语言的原因。

    这种结构体与函数指针的结合使用还有很多用途,其实也可以将公用体与函数指针结合,方法一样。这几种结合功能相当强大。在定义接口时将非常有用。
    比如在写一个设备驱动程序时,我们就要填写一个数据结构file_operations,具体的定义如下:

struct file_operations {
int (*seek) (struct inode * ,struct file *, off_t ,int);
int (*read) (struct inode * ,struct file *, char ,int);
int (*write) (struct inode * ,struct file *, off_t ,int);
int (*readdir) (struct inode * ,struct file *, struct dirent * ,int);
int (*select) (struct inode * ,struct file *, int ,select_table *);
int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long
int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);
int (*open) (struct inode * ,struct file *);
int (*release) (struct inode * ,struct file *);
int (*fsync) (struct inode * ,struct file *);
int (*fasync) (struct inode * ,struct file *,int);
int (*check_media_change) (struct inode * ,struct file *);
int (*revalidate) (dev_t dev);
}
    这个数据结构为编程人员提供了一个访问设备的公用接口,比如read,write等等。
具体设备驱动程序的编写已经超出本文范围,日后再说明。

小结:
    利用函数指针来模拟多太,讨论出函数指针的一些特殊用法。以及调用函数指针的参数无关性。

 

 


#############################################################################################################
#include "stdio.h"  
struct DEMO   //遥控器实体
{  
    char x;   // 按键
    int (*func)(int x,int y); //函数指针    //按按键
};  
 
int add2(int x,int y)   //定义遥控器发送指令
{  
    return x+y;  
}  
 
int dec2(int x,int y)   //定义遥控器发送指令
{  
    return x-y;  
}  
 
struct DEMO demo[2] =   
{  
    {1,add2},       {2,dec2}  
};  
int main(void)
{  
    printf("func%d=%d\n",demo[0].x,demo[0].func(4,3));  
    printf("func%d=%d\n",demo[1].x,demo[1].func(4,3));  
    return 0;  

说明:demo[0],demo[1]可以看做两种不同功能的遥控器实体,
demo[0].x为获取遥控器的固有属性,可以是遥控器的品牌
demo[0].func(4,3)可以抽象为同时按下4,3按键后遥控器的反应;

+++++++++++++++++++++++++++++++++++++++++++++++++++++

大致就是这样。2011/05/05

 

<think>我们参考了引用[2]和引用[3]中的内容。引用[2]指出,在C语言结构体中,可以通过定义函数指针来指向函数,从而实现在结构体中调用函数的目的。引用[3]详细介绍了结构体中定义函数指针的几种形式,以及如何定义和使用函数指针。 用户问题:如何在不使用typedef的情况下在C语言结构体中定义和使用函数指针? 我们将分步骤说明: 1. 定义结构体类型,并在其中声明函数指针成员。 2. 定义与函数指针匹配的函数(即函数签名一致:返回类型和参数类型相同)。 3. 创建结构体变量,并将函数的地址赋给结构体中的函数指针成员。 4. 通过结构体变量调用函数指针。 注意:不使用typedef意味着我们需要直接写出函数指针的类型,即按照函数指针的声明方式。 函数指针的一般声明形式: 返回类型 (*指针变量名)(参数列表); 因此,在结构体中,我们可以这样定义函数指针成员: 示例: 假设我们要定义一个结构体,其中包含一个函数指针,该函数指针指向一个无参数、无返回值的函数。 步骤1:定义结构体类型 struct MyStruct { // 其他成员... void (*my_function_pointer)(void); // 函数指针成员 }; 步骤2:定义匹配的函数 void my_function(void) { printf("Hello, this is a function without typedef.\n"); } 步骤3:使用结构体 int main() { // 创建结构体变量 struct MyStruct s; // 将函数地址赋给结构体中的函数指针成员 s.my_function_pointer = my_function; // 或者 &my_function // 通过结构体调用函数 s.my_function_pointer(); return 0; } 如果函数指针需要带参数,比如一个接受int参数并返回void的函数,则结构体中应定义为: void (*my_function_pointer)(int); 然后定义函数: void my_function_with_param(int x) { printf("Value: %d\n", x); } 赋值和调用: s.my_function_pointer = my_function_with_param; s.my_function_pointer(10); 下面我们给出一个完整的例子,包含带参数的函数指针: 示例代码: ```c #include <stdio.h> // 定义结构体,其中包含一个函数指针,该函数指针指向一个接受int参数并返回void的函数 struct MyStruct { void (*print)(int); // 函数指针成员 }; // 定义匹配的函数 void print_int(int x) { printf("The integer is: %d\n", x); } int main() { // 创建结构体变量 struct MyStruct obj; // 将函数地址赋给结构体中的函数指针成员 obj.print = print_int; // 等价于 obj.print = &print_int; // 通过结构体调用函数 obj.print(42); // 输出: The integer is: 42 return 0; } ``` 另一种情况:如果函数指针需要指向一个带返回值的函数,比如返回int,接受两个int参数: struct MyStruct { int (*compute)(int, int); }; 然后定义函数: int add(int a, int b) { return a + b; } 使用struct MyStruct obj; obj.compute = add; int result = obj.compute(3, 4); 完整示例: ```c #include <stdio.h> struct Calculator { int (*operation)(int, int); }; int add(int a, int b) { return a + b; } int main() { struct Calculator calc; calc.operation = add; int result = calc.operation(5, 7); printf("5 + 7 = %d\n", result); // 输出: 5+7=12 return 0; } ``` 总结: 1. 在结构体中直接声明函数指针成员,格式为:返回类型 (*成员名)(参数类型列表); 2. 定义与函数指针签名匹配的函数。 3. 创建结构体变量,将函数地址(函数名)赋给函数指针成员。 4. 通过结构体变量和成员名调用函数。 注意:不使用typedef时,函数指针类型的声明看起来较为复杂,但这样避免了使用额外的类型别名,直接体现了函数指针的原始语法。 引用说明: 根据引用[2]:在C语言结构体中,只能通过定义函数指针的方式,用函数指针指向相应函数,以此达到调用函数的目的[^2]。 根据引用[3]:在结构体中定义函数指针,可以采用上述形式[^3]。 §§相关问题§§ 1. 在结构体使用函数指针与在结构体外直接调用函数相比有什么优势? 2. 如何实现结构体中多个不同函数指针的动态绑定? 3. 函数指针作为结构体成员时,内存布局是怎样的? 4. 在C语言中,结构体中的函数指针能否指向静态函数?需要注意什么?</think>### 不使用typedef在结构体中定义和使用函数指针 在C语言中,即使不使用`typedef`,也能直接在结构体中定义和使用函数指针。以下是详细步骤和示例: #### 1. **基本定义方法** 在结构体中直接声明函数指针成员: ```c struct Decoder { // 函数指针成员:指向无参数无返回值的函数 void (*decode_func)(void); }; ``` - `void (*decode_func)(void)` 表示: - `decode_func`:函数指针成员名 - `void`:函数返回类型 - `(void)`:函数参数列表(无参数) #### 2. **完整使用示例** ```c #include <stdio.h> // 定义匹配的函数 void h264_decode() { printf("Decoding H.264 stream\n"); } // 结构体定义(无typedef) struct VideoPlayer { int codec_id; void (*decode)(void); // 直接定义函数指针 }; int main() { // 创建结构体实例 struct VideoPlayer player; // 函数指针赋值 player.decode = h264_decode; // 等价于 player.decode = &h264_decode; // 通过函数指针调用 player.decode(); // 输出: Decoding H.264 stream return 0; } ``` #### 3. **带参数的函数指针** ```c // 带参数的函数 void audio_decode(int bitrate) { printf("Decoding audio at %dkbps\n", bitrate); } // 结构体定义 struct AudioPlayer { void (*decode)(int); // 指向带int参数的函数 }; int main() { struct AudioPlayer player; player.decode = audio_decode; player.decode(256); // 输出: Decoding audio at 256kbps return 0; } ``` #### 4. **结构体初始化技巧** 可在声明时直接初始化函数指针: ```c struct Device { void (*init)(void); } usb_device = { .init = usb_initialize // 直接初始化 }; // 匹配的函数 void usb_initialize() { printf("USB device initialized\n"); } ``` #### 5. **函数指针数组** 在结构体中定义函数指针数组: ```c struct CommandHandler { void (*commands[3])(void); // 函数指针数组 }; int main() { void cmd_start() { printf("Start\n"); } void cmd_stop() { printf("Stop\n"); } struct CommandHandler handler; handler.commands[0] = cmd_start; handler.commands[1] = cmd_stop; handler.commands[0](); // 输出: Start handler.commands[1](); // 输出: Stop return 0; } ``` #### 关键区别:typedef vs 直接定义 | 特性 | 使用typedef | 直接定义 | |--------------------|----------------------------|-----------------------------| | 类型名 | `decode_handle_t` | 无,需写完整声明 | | 结构体成员声明 | `decode_handle_t decoder;` | `void (*decode)(void);` | | 可读性 | 高(语义清晰) | 低(需解析复杂语法) | | 函数指针赋值 | 相同 | 相同 | | 函数调用 | 相同 | 相同 | #### 使用场景 这种直接定义方式适用于: 1. **单次使用函数指针**(不需要复用类型) 2. **简单回调机制**(如设备驱动[^3]) 3. **嵌入式系统**(减少类型抽象层) 4. **协议解析**(如自定义网络协议处理) > 引用说明:在C语言结构体中直接定义函数指针是实现回调的标准方法,如引用[2][3]所示[^2][^3]。这种方式避免了额外的类型抽象,但牺牲了部分代码可读性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值