Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C(C99)中嵌套函数调用的限制_C_C99 - Fatal编程技术网

C(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);

根据C99,函数的嵌套调用是否有限制

例如:

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个字符
18) 实现应尽可能避免强加固定的翻译限制


如果嵌套调用的次数太多,以至于开始担心限制,那么您做得不对。这样的代码将无法读取和维护。别想写那样的代码,我不是在写代码。这是一些自动生成的代码。我想您只受堆栈大小的限制。@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)