1. 程式人生 > >C結構體中的函式指標與函式

C結構體中的函式指標與函式

1. 函式指標
一般的函式指標可以這麼定義:
int(*func)(int,int);
表示一個指向含有兩個int引數並且返回值是int形式的任何一個函式指標. 假如存在這樣的一個函式:
int add2(int x,int y)
{
return x+y;
}
那麼在實際使用指標func時可以這樣實現:
func=&add2; //指標賦值,或者func=add2; add2與&add2意義相同
printf("func(3,4)=%d/n",func(3,4));

事實上,為了程式碼的移植考慮,一般使用typedef定義函式指標型別.
typedef int(*FUN)(int,int);
FUN func=&add2;
func();

2.結構體中包含函式指標

其實在結構體中,也可以像一般變數一樣,包含函式指標變數.下面是一種簡單的實現.
#include "stdio.h"
struct DEMO
{
int x,y;
int (*func)(int,int); //函式指標
};
int add2(int x,int y)
{
return x+y;
}
void main()
{
struct DEMO demo;
demo.func=&add2; //結構體函式指標賦值
printf("func(3,4)=%d/n",demo.func(3,4));
}
上面的檔案儲存為mytest.c,在VC6.0和gcc4中編譯通過.

3.結構體中的函式

既然C++在介紹類的時候說過,類是取代結構體的.可見結構體的功能並非我們平時用到的這麼簡單,沒有太多人知道結構體中也可以有自己的函式成員.
舉個例子:
#include "stdio.h"
struct DEMO
{
int m;

DEMO(int k) //建構函式
{
this->m=k;
printf("after init,m=%d/n",m);
}

void func()//一般函式
{
printf("function of struct./n");
}
};

void main()
{
struct DEMO demo(33);
demo.func();
}

  儲存為mytest1.c , VC6.0和gcc編譯都會出錯. 這可能說明標準C是不支援結構體包括函式成員形式的(因為字尾.c使得VC或gcc選擇c編譯器). 但是如果將檔案字尾改為.cpp(也就是選擇c++編譯),就不再有錯誤了,得到結果:
after init,m=33
function of struct.

也就是說,在C++中允許結構體包含函式成員,而標準C不支援. 進一步發現,c++中甚至允許結構體中含有建構函式、過載、public/private等等.這樣看來,結構體真的與類越來越靠近相似了!

C++擴充了結構體的功能。但C++中為了介紹面向物件的類,卻淡化了同樣精彩的結構體。當我們寫一些小程式而覺得沒有必要去構造類的時候,選擇結構體確實會方便很多.


========================================
函式指標的說明:

   已知函式指標定義宣告 float (*h)();
   怎麼理解語句? (*(void (*)())0)(); 
   這是一個C語句,表示(*p)(); 其中p指向0, 0被強制轉換成(void (*)())格式。
   或者用typedef將上面式子分成兩步:
   typedef void (*pFUNC)(); //pFUNC表示一種函式指標型別,這樣的函式式void fun()形式.
   (*(pFunc)0)();

  對於這一點,在unix程式設計signal方面用到過,如下:
    signal函式原型: void (*signal(int signo,void (*func)(int)))(int);
    其第二個引數func是一個void型函式指標(該函式引數為int),並且返回一個void型函式指標(該函式引數為int),簡化這個定義, 可以typedef void Sigfunc(int);  然後signal函式原形寫為 Sigfunc* signal(int,Sigfunc*);
     三個常量用於替代這樣的指標。定義如下:
#define SIG_ERR (void (*)())-1
#define SIG_DFL (void (*)())0
#define SIG_IGN (void (*)())1

函式應用
if(signal(SIGUSR1,sig_func)==SIG_ERR)
    err_sys("can't catch SIGUSR1");