2017-04-24 125 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委员会注意到语言的谨慎,保守的看法扩展名“。

很难说一个嵌套函数提供显着好处的情况,因此即使某些实现支持它们,它们也不被认为是标准的,这并不奇怪。

一般而言,自那时起,标准工作至少同样保守,再次很难在实施者中看到很多支持添加这样的功能。

在一天结束时,如果您担心某些函数超出其预期用途并且(逻辑上)是一个给定函数的子函数,那么将其静态链接并引入另一个源文件,甚至是整个翻译单元。