为什么早期版本的C必须在开头声明变量?

Amr*_*hna 15 c c++ compiler-construction

我已经经历了C的一些历史,我发现在早期版本的C中,就像在C89标准中一样,必须在块的开头声明变量.

但我也发现C99标准规范有一些放松,其中变量可以在使用之前在任何地方声明.

我的问题是为什么早期版本强制要求?我的重点是要知道当时设计编译器是否存在技术上的困难,这使他们无法在任何时候识别声明.

另外,从我理解的编译器设计角度来看,在C89中有这样的限制,在中间文件的帮助下很容易处理变量声明和用法来存储映射.但有没有使用中间文件处理案例的方法,比如一些基于内存的存储?

Ton*_*roy 19

如果编译器预先看到所有本地/自动变量的合并列表,它可以立即计算出将堆栈指针移动到它们的保留堆栈内存的总量 - 只需对堆栈指针执行一次操作.如果它在函数中遇到它们处理变量和drabs中的变量,逐步移动堆栈指针,那么最终会有更多专用于堆栈设置和堆栈指针更新的操作码.每当执行进一步的函数调用时,堆栈指针都是最新的非常重要.较新的编译器会做一些额外的工作来修补在考虑所有函数之后移动堆栈指针的数量.(我觉得这个努力是如此之小,以至于早期标准的形成更多的是因为知道前面做什么而不是更灵活的努力的概念吸引力,但如果你只是想让事情变得有效 - 为什么要做出额外的努力?)

  • 想到这一点的必然结果是,在计算机编译C89之前和之前的计算机的史前时,在回去开始编译和发出代码之前,它需要花费大量的时间来预先解析每个块以找到所有本地人,如果编译器已经以这种一次通过的方式构建. (4认同)
  • @ratchetfreak:你不能禁止goto进入一个具有自己声明的变量的块,C89允许它.AC编译器必须通过考虑源和目标处的"格局"来处理goto,包括堆栈位置以及可能在哪些寄存器中的变量,并且在跳转之前(或不太可能,之后)进行任何调整.所以`if(something)goto X;`不一定最终作为针对X的条件分支操作码,即使CPU有一个. (3认同)
  • 难道你不需要回补(或者在函数内多次递增堆栈指针的效率),因为新的变量仍然可以在内部块中声明吗? (2认同)
  • @immibis在goto上怎么样? (2认同)

Yu *_*Hao 13

C99基本原理没有直接解释为什么它不在C89中被允许,但确实说它是在C99中添加的,因为它被其他语言所允许并且它被认为是有用的.

国际标准的基本原理 - 编程语言 - C.

§6.2.4对象的存储持续时间

C99:C89的新功能要求块中的所有声明都在任何语句之前发生.另一方面,许多类似于C的语言(例如Algol 68和C++)允许以任意方式混合声明和语句.已发现此功能很有用,并已添加到C99中.