C (C99) 中嵌套函数调用的限制

Limit for nested function calls in C (C99)

按照C99,函数的嵌套调用有限制吗?

示例:

result = fn1( fn2( fn3( ... fnN(parN1, parN2) ... ), par2), par1);

注意:这段代码绝对不是一个好习惯,因为很难管理;但是,此代码是从模型自动生成的,因此不存在可管理性问题。

没有。由于这些功能是一一执行的,所以没有问题。

int res;
res = fnN(parN1, parN2);
....
res = fn2(res, par2);
res = fn1(res, par1);

执行是线性的,之前的结果用于下一个函数调用。

编辑:如评论中所述,解析器 and/or 编译器可能存在问题,无法处理如此难看的代码。

如果这不是一个纯理论问题,答案很可能是"Try to rewrite your code so you don't need to do that, because the limit is more than enough for most sane use cases"。如果这纯粹是理论上的,或者您确实需要担心这个限制而不能只是重写,请继续阅读。


C11 标准的第 5.2.4 节 (latest draft, which is freely available and almost identical) 指定了对需要 支持的实现的各种限制。如果我没看错,您最多可以嵌套 63 层。

但是,允许实现支持更多,在实践中他们可能会支持。我很难找到适合 GCC 的文档(我找到的最接近的是预处理器中的表达式),但我希望它没有硬性限制,除了编译时的系统资源。

没有。没有限制。

例如,这是一个 C 代码段:

int func1(int a){return a;}
int func2(int a){return a;}
int func3(int a){return a;}

void main()
{
func1(func2(func3(16)));
}

对应的汇编代码为:

0000000000000024 <main>:
  24:   55                      push   %rbp
  25:   48 89 e5                mov    %rsp,%rbp
  28:   bf 10 00 00 00          mov    [=11=]x10,%edi
  2d:   e8 00 00 00 00          callq  32 <main+0xe>
  32:   89 c7                   mov    %eax,%edi
  34:   e8 00 00 00 00          callq  39 <main+0x15>
  39:   89 c7                   mov    %eax,%edi
  3b:   e8 00 00 00 00          callq  40 <main+0x1c>
  40:   90                      nop
  41:   5d                      pop    %rbp
  42:   c3                      retq   

%edi寄存器存储每个函数的结果,%eax寄存器存储参数。如您所见,三个 callq 指令对应三个函数调用。也就是说,这些嵌套的函数是一个一个被调用的。堆栈不用担心。


如评论中所述,当代码嵌套太深时,编译器可能会崩溃。 我写了一个简单的 Python 脚本来测试这个。

nest = 64000

funcs=""
call=""

for i in range(1, nest+1):
    funcs += "int func%d(int a){return a;}\n" %i
    call += "func%d(" %i

call += str(1) # parameter
call += ")" * nest + ";" # right parenthesis

content = '''
%s
void main()
{
%s
}
''' %(funcs, call)

with open("test.c", "w") as fd:
    fd.write(content)

nest = 64000可以,但是640000会造成gcc-5.real: internal compiler error: Segmentation fault (program cc1).

没有直接的限制,但编译器只需要允许各种类别的一些最小限制:

来自C11 standard

5.2.4.1 Translation limits 1 The implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits: 18)

...

  • 63 nesting levels of parenthesized expressions within a full expression

...

  • 4095 characters in a logical source line

18) Implementations should avoid imposing fixed translation limits whenever possible