//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