[英]What's the difference between these 2 declarations?
這是一個簡單而細膩的問題。 有人可以解釋a和b之間的區別嗎?
void (*a)(int x, int y)
void (*b(int x, int y))(int)
這個問題來自以下Linux函數聲明:
void (*signal(int sig, void (*func)(int)))(int);
以下程序是一個很好的演示。
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void ouch(int sig)
{
printf("OUCH! - I got signal %d\n", sig);
signal(SIGINT, SIG_DFL);
}
void (*g())(int) // just like the b
{
return ouch;
}
int main()
{
void (*f)(int); // just like the a
f=g();
signal(SIGINT, f);
while(1)
{
printf("Hello, world!\n");
sleep(1);
}
}
C的設計者選擇以類型的用例盡可能匹配使用該類型獲取值的方式來命名其類型。 所以,例如,當你有一個類似的聲明時
int a;
你可以說a
得到一個int
。 如果你有類似的類型
int *a;
然后,你必須取消引用a
寫*a
得到一個int
。
您可以使用類似的,雖然更復雜的邏輯來解碼您發布的類型。 讓我們開始吧
void (*a)(int x, int y)
這就是說,如果你解引用a
(通過編寫*a
),那還有什么留給你的東西,看起來像
void (int x, int y)
這是一個函數接受兩個int
並返回void
。 換句話說,您可以將a
視為指向函數的指針; 一旦解除引用,你就會恢復功能。
現在這個野獸:
void (*b(int x, int y))(int)
這個比較棘手。 這個想法如下。 如果你拿b
並傳入兩個參數,那么你會得到一些看起來像這樣的東西:
void (*)(int)
這是一個指向函數的指針,它接受一個int
並返回void
。 換句話說, b
是一個帶有兩個參數的函數,然后返回一個帶有一個參數並返回void
的函數指針。
解碼這些類型有點棘手,所以通常你不會以這種方式編寫,而是使用typedef
簡化操作。 例如,這個typedef:
typedef void (*FunctionTakingTwoInts)(int, int);
說你可以使用FunctionTakingTwoInts
定義一個函數指針,該函數指針指向一個接受兩個int
並返回void
的函數。 從這里,申報a
簡化了下來
FunctionTakingTwoInts a;
同樣,在b
的情況下,讓我們定義類型
typedef void (*FunctionTakingOneInt)(int);
現在,我們可以將b
重寫為
FunctionTakingOneInt b(int x, int y);
從這個角度來看,我認為這種類型實際意味着更清楚。
希望這可以幫助!
簡短版本: a
聲明指向函數的指針。 b
聲明一個返回指向函數的指針的函數。
更長版本:您知道以下模式來聲明指向函數的指針
void (*f)(int x, int y)
現在,取“f”,並修改它。 例如,將其設為數組
void (*f[3])(int x, int y)
現在,您沒有指向函數的指針,而是有一個指向函數的指針數組。 現在,如果您將其修改為函數而不是數組,則將第一個聲明轉換為第二個聲明
void (*f(void))(int x, int y)
您已將其修改為返回指向函數的指針的函數。 您的聲明不是沒有像這種情況那樣的參數,而是有兩個參數。 其中一個是int
,另一個是另一個指向函數的指針。
使用typedef比組合C聲明符更容易。
// your example
typedef void signal_fn(int);
signal_fn *signal(int sig, signal_fn *func);
// my example above
typedef void f_fn(int x, int y);
f_fn *f(void);
用foo替換(*a)
:
void foo(int x, int y);
a
是指向這樣的函數的指針。
同樣,用foo替換(*b(int x, int y))
:
void foo(int);
b(int x, int y)
返回一個指向類似函數的指針。
http://cdecl.org/可以為這樣的聲明提供很好的幫助。 不幸的是,它不處理命名的函數參數,因此必須刪除它們。 喂養
void( signal(int,void( )(int)))(int)
得到:
聲明信號為函數(int,指向函數的指針(int)返回void)返回指向函數(int)返回void的指針
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.