C(C99)中嵌套函数调用的限制
根据C99,函数的嵌套调用是否有限制 例如:C(C99)中嵌套函数调用的限制,c,c99,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);
result = fn1( fn2( fn3( ... fnN(parN1, parN2) ... ), par2), par1);
注意:此代码绝对不是一个好的实践,因为难以管理;但是,此代码是从模型自动生成的,因此可管理性问题不适用。否。由于这些函数是逐个执行的,因此不存在任何问题
int res;
res = fnN(parN1, parN2);
....
res = fn2(res, par2);
res = fn1(res, par1);
执行与下一个函数调用使用的上一个结果是线性的
编辑:正如注释中所解释的,解析器和/或编译器在处理如此丑陋的代码时可能会出现问题。如果这不是一个纯粹的理论问题,答案可能是“尝试重写代码,这样你就不需要这样做,因为对于大多数正常的用例来说,限制已经足够了”。如果这纯粹是理论上的,或者你真的需要担心这个限制,不能只是重写,请继续阅读
C11标准()第5.2.4节规定了需要支持哪些实现的各种限制。如果我读对了,你可以达到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 $0x10,%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
nest=64000
可以,但640000
将导致gcc-5。实际:内部编译器错误:分段错误(程序cc1)
没有直接的限制,但编译器只需要为各种类别允许一些最小限制:
从:
5.2.4.1翻译限制
1实现应能够翻译和执行至少一个程序,该程序至少包含以下每一个限制的一个实例:18)
- 63完整表达式中括号表达式的嵌套级别
- 逻辑源行中有4095个字符
如果嵌套调用的次数太多,以至于开始担心限制,那么您做得不对。这样的代码将无法读取和维护。别想写那样的代码,我不是在写代码。这是一些自动生成的代码。我想您只受堆栈大小的限制。@AndrejsCainikovs函数调用不是真正嵌套的,而是按顺序嵌套的。@Gerhardh如果查看汇编,您将看到所有寄存器都被推送到堆栈中,并在执行完成后弹出。现在将这几个寄存器乘以10k,您可能会达到极限。例如,我目前正在使用堆栈为4k的嵌入式应用程序。但是编译器本身可能会在解析器中或递归操作过深AST的任何地方耗尽空间。没有任何特定的运行时限制,但可能存在编译时间限制。在实践中,让代码生成保持在4095个字符行和63个深括号可能比实际情况更困难,但您至少应该知道这些限制。不是在程序运行时,而是在编译时可能会耗尽内存(或者更可能会填满一些数据结构)。编译器不需要支持任意嵌套。@DanielH你说得对。GCC可能会因为大量嵌套函数而终止。限制可能取决于系统,但只要大多数系统可以达到6400,我就不认为在实践中会出现问题。请注意,大多数实现都遵循脚注18的规定,我怀疑您是否会找到一个常用的编译器,其限制或低或低。
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)