函式指標的 Typedef

我們可以使用 typedef 來簡化函式指標的使用。想象一下,我們有一些函式,都具有相同的簽名,使用他們的引數以不同的方式列印出來:

#include<stdio.h>

void print_to_n(int n)
{
    for (int i = 1; i <= n; ++i)
        printf("%d\n", i);
}

void print_n(int n)
{
    printf("%d\n, n);
}

現在我們可以使用 typedef 來建立一個名為 printer 的命名函式指標型別:

typedef void (*printer_t)(int);

這將建立一個名為 printer_t 的型別,用於指向函式的指標,該函式接受單個 int 引數並且不返回任何內容,這與我們上面的函式的簽名相匹配。要使用它,我們建立一個建立型別的變數,併為其指定一個有問題的函式:

printer_t p = &print_to_n;
void (*p)(int) = &print_to_n; // This would be required without the type

然後呼叫函式指標變數指向的函式:

p(5);           // Prints 1 2 3 4 5 on separate lines
(*p)(5);        // So does this

因此,typedef 在處理函式指標時允許更簡單的語法。當函式指標用於更復雜的情況時,例如函式的引數,這一點就變得更加明顯。

如果你使用的函式將函式指標作為引數而未定義函式指標型別,則函式定義將是,

void foo (void (*printer)(int), int y){
    //code
    printer(y);
    //code
}

但是,使用 typedef 它是:

void foo (printer_t printer, int y){
    //code
    printer(y);
    //code
}

同樣,函式可以返回函式指標,並且再次使用 typedef 可以使語法更簡單。

一個典型的例子是 <signal.h>signal 功能。它的宣告(來自 C 標準)是:

void (*signal(int sig, void (*func)(int)))(int);

這是一個帶有兩個引數的函式 - 一個 int 和一個指向函式的指標,該函式將 int 作為引數並且不返回任何內容 - 並返回一個指向函式的指標,就像它的第二個引數一樣。

如果我們將型別 SigCatcher 定義為指向函式型別的指標的別名:

typedef void (*SigCatcher)(int);

然後我們可以使用以下方式宣告 signal()

SigCatcher signal(int sig, SigCatcher func);

總的來說,這更容易理解(即使 C 標準沒有選擇定義型別來完成工作)。signal 函式有兩個引數,一個 int 和一個 SigCatcher,它返回一個 SigCatcher - 其中 SigCatcher 是一個指向一個函式的指標,該函式接受一個 int 引數並且什麼都不返回。

雖然使用 typedef 名稱作為指向函式型別的指標可以使生活更輕鬆,但它也可能導致後來維護程式碼的其他人感到困惑,因此請謹慎使用並使用適當的文件。另請參見功能指標