參考文獻: https://gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Nested-Functions.html
巢狀函數是定義在另一個函數內部的函數。巢狀函數在GNU C中被支援作爲擴充套件,但是GNU c++不支援, 巢狀函數的名稱對於定義它的塊來說是區域性的。
例如: 我們的函數傳入一個參數並計算這個參數的四次方返回,我們可以用x * x * x * x * x表示,也可以使用pow函數,但是這個例子僅僅是爲了說明巢狀函數的使用。
巢狀函數可以存取所有在它的定義塊中的變數,比如,我們將原本的quadratic定義爲:
int quadratic() {
return number * number;
}
源程式就成了這樣:
#include <stdio.h>
int fourthPower(int number) {
int quadratic() {
return number * number;
}
return quadratic(number) * quadratic(number);
}
int main() {
printf("10 ^ 4 = %d\n", fourthPower(10));
return 0;
}
編譯執行結果和上面相同,就不展示了。
結論: 在允許變數定義的地方,函數內都允許巢狀函數定義。巢狀函數可以使用所定義處的區域性變數
我們繼續往下看:
It is possible to call the nested function from outside the scope of its name by storing its address or passing the address to another function
通過儲存巢狀函數的地址或將地址傳遞給另一個函數,可以從其名稱的作用域之外呼叫巢狀函數:
int nestedFunctionPower(int number) {
int quadratic() {
return number * number;
}
int(*qua)() = quadratic;
return (*qua)(number);
}
GCC使用一種稱爲trampolines的技術來實現獲取巢狀函數的地址。這種技術在c++的詞法閉包中有描述(Thomas M. Breuel, USENIX C++ Conference Proceedings, October 17-21, 1988).
文獻中還有一句話:
A nested function can jump to a label inherited from a containing function, provided the label is explicitly declared in the containing function (see Local Labels). Such a jump returns instantly to the containing function, exiting the nested function that did the goto and any intermediate functions as well
總的來說就是在巢狀函數裏面可以使用goto 蹦噠到外面,因爲goto的使用很有爭議,在這裏我把文獻中的例子複製過來
bar (int *array, int offset, int size)
{
__label__ failure;
int access (int *array, int index)
{
if (index > size)
goto failure;
return array[index + offset];
}
int i;
/* … */
for (i = 0; i < size; i++)
/* … */ access (array, i) /* … */
/* … */
return 0;
/* Control comes here from access
if it detects an error. */
failure:
return -1;
}
如果您需要在巢狀函數的定義之前宣告它,請使用auto(否則對於函數宣告來說,這是毫無意義的)。