在 C 中,i++
通常不等同于,i=i+1
因为两者产生不同的表达式值。++i
等价于,i=i+1
因为它们产生相同的表达式值。
i
在未使用上述三个表达式 with 中的任何一个的情况下,这三个是相同的。如果它是一个好的编译器,它可以优化掉由i++
.
这个临时变量之所以活跃,是因为i++
它决定了以下两件事:
- 的原始值
i
由表达式返回i++
i
增加 1
如果您首先取 的原始值 i
然后递增i
,那么原始(现在旧的)值i
必须存在于某个地方(内存或寄存器,无关紧要),因为它不能存在于现在递增的变量i
中。那是你的临时变量。
如果,OTOH,您首先增加i
1,然后再次,您必须在某处(在寄存器或内存中)创建一个等于i-1
撤消增量的值,因此可以获得旧的(预增加的)值作为结果表达式i++
。
有了++i
和i=i+1
事情就简单多了。这些表达式要求做两件事:
i
增加
- 的新值
i
被返回
在这里很自然地先递增i
然后取其值。你不必有一对i
和i+1
(或i-1
和i
)的值,旧的和新的。我们在这里只需要新的。
现在,从编译器不太擅长优化的时代开始就有旧书和老人。从那里人们可以得到一个i++
可能比++i
. 在实践中观察到差异,而不是弥补。这是真实的,有些人可能认为今天仍然如此。
还可以尝试分析两(三)个递增表达式之间的差异,并看到确实可能需要做一些额外的操作,并为临时变量使用额外的存储单元以防i++
. 在这一点上,这个人可能看不到什么时候不需要这个临时的,或者如何检测是否有必要。这是有关上述差异的另一种可能性。
而且,当然,人们一直都喜欢拖钓。:)
至于编译器开发人员懒惰......我不认为他们是。这就是为什么。
回到过去,计算机比现在慢得多,它们携带的 RAM 也少得多。
即使在那时,编写一个体面的优化编译器也是可能的。
问题是用于优化的额外代码使编译器明显变大变慢。如果它更大,可以运行它的计算机更少,可以使用它来编译代码的程序员也更少。如果它比其他编译器慢,人们会更喜欢其他编译器,因为人们讨厌坐着等待。
一个例子:我。在 90 年代中期,我确实可以使用 Borland 的 Turbo C/C++。但直到 90 年代末、0 年代初,我才考虑学习和使用 C。原因?Borland 的 C/C++ 比他们的 Pascal 慢得多,而且我的 PC 也不是很好。等待代码编译是痛苦的。事情就是这样。我首先掌握了 Pascal,后来才回到 C 和 C++。
因此,更智能、更大和更慢的编译器正在花费编译器用户的金钱和时间。至少在积极开发期间,这仍然是一个非常重要的产品阶段,即使最终产品是使用不同的编译器编译的。
您也不应该忘记,使用当时的基本工具开发和管理一大段编译器代码也不是很有趣。只是现在您可以拥有一个不错的 IDE(而不是一个!),其中包含调试器、语法突出显示、自动完成等所有功能、源代码管理、简单的文件比较、Internet/StackOverflow 等等……我们可以现在有多个 20+" 显示器连接到 PC!现在我们正在谈论生产力!:)
真的,我们今天有很棒的工具和设备。20、30、40 年前,人们只能想象或预测它们,但尚未使用。
事情变得更加艰难。而且,虽然我不打算在这里发表声明,但我不会惊讶地发现,当时编程还没有像现在这样商品化,优秀和优秀的程序员比今天更多。当然,这不是绝对数字,而是相对数字。
所以,我怀疑编译器的人是懒惰的。
在网上查找所谓的Small C
. 它是一个通用术语,用于仅实现 C 语言最重要的特性的一个非常简单且功能减少的 C 编译器。您会发现一些由Ron Cain
, James Hendrix
(80 年代初)和其他实现以及从这些实现(例如 RatC/Lancaster 由Bob Berry
和实现相同Brian Meekings
)。
如果您查看其中任何一个的代码Small C's
,您会发现最小代码大小约为 50+ KB 和 2+ KLOC,这只是从 C 到汇编代码的翻译器!在某些时候,有人需要用汇编器来组装它。
我无法想象在像 8 位家用计算机这样的项目上舒适地工作,例如 ZX-Spectrum(我小时候就有),它可以有最大 48KB 的 RAM,CPU 运行在 ~3MHz ,所有存储都在磁带录音机上,数据传输速率约为 10KB/min,屏幕为 32x24,甚至不是 80x25。
80 年代初的所有 Small C 代码,几乎不适合计算机的内存,并没有优化任何东西!