2017-04-24 141 views
0

C標準(ANSI [C89],C99,C11)中不允許嵌套函數(塊作用域中的函數聲明)。爲什麼C中的嵌套函數違背C標準

但我無法在C標準中找到它。

編輯:

爲什麼函數定義不能在函數的定義(複合語句)?

+1

標準的存在是陳述什麼構成一個有效的C程序,而不是說明數百萬的事情不是標準的 – StoryTeller

+1

一個標準正式地說明你可以做什麼,而不是你不能做什麼。由於標準中沒有聲明可以定義嵌套函數,所以不能。 –

+0

@PaulOgilvie 6.2.1.4聲明,如果聲明標識符的聲明符或類型說明符出現在塊內或函數定義中的參數聲明列表中,則該標識符具有塊範圍,該範圍終止於關聯塊的末尾。 6.7.5.3聲明瞭函數聲明器。那麼根據它,函數聲明符可以是塊範圍? – user1448742

回答

5

功能聲明和函數定義之間存在差異。一個聲明只是聲明一個函數的存在,而一個定義則定義了該函數。

int f(void) { /* ... */ } // function definition 
int f(void);    // function declaration 

在6.9.1一個函數的語法被定義爲

函數的定義: 聲明-符說明符聲明列表選擇化合物-statment

在6.8.2,你可以在複合陳述中加入的東西被定義爲聲明聲明。函數定義不被認爲是這些語法中的任何一個。

所以,函數聲明在函數中是合法的,但函數定義不是例如

int main(int argc, char*argv[]) 
{ 
    int f(void);    // legal 
    int g(void) { return 1; } ; // ILLEGAL 

    // blah blah 
} 
-1

嵌套或私有函數是許多C編譯器過去允許的,但不是C標準的一部分,現在很難找到支持它們的編譯器,當然默認情況下是這樣。

標準由委員會決定,嵌套函數將會是他們已經討論過的東西,並且會有一個基本原理,但我不知道它是什麼,也不是大多數C程序員。嵌套函數本質上並不是一個壞主意,但通過編寫一個靜態文件範圍函數(這是創建標準化的私有函數的方法),您幾乎可以實現所有好處。

+0

我不會叫gcc一個「罕見的編譯器」。 – Olaf

+1

因爲它使用了大量的擴展(嵌套函數是其中之一),所以我不會將gcc作爲嚴格符合標準的編譯器(默認情況下)。 – InternetAussie

+0

@InternetAussie擴展符合標準,如果他們不違反任何合規計劃 –

0

它可能沒有直接說明,但如果你通過函數定義的語法工作,你會發現它們在語法中不被接受。

爲什麼?根據丹尼斯里奇(誰是一個權威的問題)看起來他們從一開始就被排除在外:

「程序可以嵌套在BCPL中,但不能引用在包含過程中定義的非靜態對象B和C通過施加更嚴格的規則來避免這種限制:完全沒有嵌套的程序。「

https://www.bell-labs.com/usr/dmr/www/chist.html

這是幽默,以避免限制通過施加更嚴厲的一個。我認爲這是一個簡化的操作。嵌套過程增加了編譯器的複雜性(裏奇非常熱衷於限制當時的機器)並且增加了很少的價值。

標準化過程(聰明)從來沒有見過爲契機,無可奈何地延長C和(來自同一文檔):

「從一開始,X3J11委員會注意到語言的謹慎,保守的看法擴展名「。

很難說一個嵌套函數提供顯着好處的情況,因此即使某些實現支持它們,它們也不被認爲是標準的,這並不奇怪。

一般而言,自那時起,標準工作至少同樣保守,再次很難在實施者中看到很多支持添加這樣的功能。

在一天結束時,如果您擔心某些函數超出其預期用途並且(邏輯上)是一個給定函數的子函數,那麼將其靜態鏈接並引入另一個源文件,甚至是整個翻譯單元。