Jenis "spiral" tidak sesuai dengan aturan yang didahulukan berikut ini:
T *a[] -- a is an array of pointer to T
T (*a)[] -- a is a pointer to an array of T
T *f() -- f is a function returning a pointer to T
T (*f)() -- f is a pointer to a function returning T
Subskrip []
dan fungsi panggilan ()
operator memiliki prioritas lebih tinggi daripada unary *
, jadi *f()
diuraikan sebagai *(f())
dan *a[]
diuraikan sebagai *(a[])
.
Jadi jika Anda ingin pointer ke array atau pointer ke suatu fungsi, maka Anda perlu mengelompokkan secara eksplisit *
dengan pengenal, seperti dalam (*a)[]
atau (*f)()
.
Kemudian Anda menyadari itu a
dan f
bisa menjadi ekspresi yang lebih rumit dari sekadar pengidentifikasi; di T (*a)[N]
, a
bisa berupa pengidentifikasi sederhana, atau bisa berupa pemanggilan fungsi seperti (*f())[N]
( a
-> f()
), atau bisa berupa array seperti (*p[M])[N]
, ( a
-> p[M]
), atau bisa berupa array pointer ke fungsi seperti (*(*p[M])())[N]
( a
-> (*p[M])()
), dll.
Akan lebih baik jika operator tipuan *
adalah postfix bukannya unary, yang akan membuat deklarasi agak lebih mudah dibaca dari kiri ke kanan ( void f[]*()*();
pasti mengalir lebih baik daripada void (*(*f[])())()
), tetapi ternyata tidak.
Saat Anda menemukan deklarasi berbulu seperti itu, mulailah dengan menemukan pengidentifikasi paling kiri dan menerapkan aturan prioritas di atas, menerapkannya secara rekursif ke parameter fungsi apa pun:
f -- f
f[] -- is an array
*f[] -- of pointers ([] has higher precedence than *)
(*f[])() -- to functions
*(*f[])() -- returning pointers
(*(*f[])())() -- to functions
void (*(*f[])())(); -- returning void
The signal
fungsi di perpustakaan standar mungkin spesimen tipe untuk jenis kegilaan:
signal -- signal
signal( ) -- is a function with parameters
signal( sig, ) -- sig
signal(int sig, ) -- which is an int and
signal(int sig, func ) -- func
signal(int sig, *func ) -- which is a pointer
signal(int sig, (*func)(int)) -- to a function taking an int
signal(int sig, void (*func)(int)) -- returning void
*signal(int sig, void (*func)(int)) -- returning a pointer
(*signal(int sig, void (*func)(int)))(int) -- to a function taking an int
void (*signal(int sig, void (*func)(int)))(int); -- and returning void
Pada titik ini kebanyakan orang mengatakan "use typedefs", yang tentunya merupakan opsi:
typedef void outerfunc(void);
typedef outerfunc *innerfunc(void);
innerfunc *f[N];
Tapi...
Bagaimana Anda akan menggunakan f
ekspresi? Anda tahu itu adalah array pointer, tetapi bagaimana Anda menggunakannya untuk menjalankan fungsi yang benar? Anda harus memeriksa typedefs dan memecahkan sintaks yang benar. Sebaliknya, versi "telanjang" cukup menarik perhatian, tetapi ia memberi tahu Anda bagaimana tepatnya menggunakan f
ekspresi (yaitu (*(*f[i])())();
, dengan asumsi kedua fungsi tidak mengambil argumen).