【问题标题】:What purpose does the pre-increment operator serve in C? [duplicate]预增量运算符在 C 中的作用是什么? [复制]
【发布时间】:2017-01-31 18:13:51
【问题描述】:

在 C 及其许多衍生物中,i++ 递增 i 并在递增之前计算为 i 的值,++i 递增 i 并计算为 i 的值 在之后增加了。

我可以看到特定增量运算符的推理;当时许多处理器都有一个特殊的增量操作码,它比加法更快,并且在概念上“增量”与“加法”是不同的想法,理论上让它们以不同的方式编写可能会使代码更具可读性。

我不明白的是需要预增量运算符。这样写就不能有什么实际用途吗?

#This...
x = i++;
#becomes this:
x = i; 
++i;

可能有我不知道的历史原因吗?您是否无法“丢弃”原始 C 版本中运算符的返回值?

【问题讨论】:

  • 可以编辑此问题以将其纳入范围吗?我很乐意编辑我的答案并添加一些历史背景,但在问题被搁置之前,我没有必要再做任何工作。我还需要知道正在处理哪些增量运算符(请原谅双关语)。
  • This question is being discussed on meta 在这里被删除后是re-asked in a clarified form on Programmers。为了在这些讨论进行期间保持透明,我已在此处取消删除,并将实施临时(1 天)锁定。

标签: c++ c language-design


【解决方案1】:

一个原因是它允许生成高效的代码,而无需在编译器中进行任何花哨的优化阶段,前提是程序员知道他(或她)在做什么。例如,当将字符从一个缓冲区复制到另一个缓冲区时,您可能会:

register char *ptr1;
register char *ptr2;
...
for ( ... ) {
    *ptr1++ = *ptr2++; /* post-increment */
}

我曾经使用过的编译器(在专有小型计算机上)会为赋值生成以下寄存器操作:

load  $r1,*$a1++       // load $r1 from address in $a1 and increment $a1
store $r1,*$a2++       // store $r1 at address in $a2 and increment $a2

我忘记了实际的操作码。编译器不包含优化阶段,但它生成的代码非常紧凑,前提是您了解编译器和机器架构。它可以做到这一点,因为硬件架构对地址寄存器和通用寄存器都有预减和后增寻址模式。据我所知,没有预递增和后递减寻址模式,但你可以不用这些。

我相信最初开发 C 的 DEC 小型计算机具有这种寻址模式。我工作的机器不是 DEC 制造的,但架构非常相似。

为编译器计划了一个优化阶段。然而,它主要由系统程序员使用,当他们看到生成的代码有多好时,优化阶段的实现就被悄悄搁置了。

C 设计的全部基本原理是允许创建简单且可移植的编译器,这些编译器将生成合理高效的代码,而中间代码优化最少(或没有)。出于这个原因,递增和递减运算符以及复合赋值运算符在早期 C 编译器生成紧凑高效的代码中发挥了重要作用。它们不仅仅是 Niklaus Wirth 等人提出的语法糖。

【讨论】:

    【解决方案2】:

    例如,您可以这样做

    While (++i < threshold) [do something];
    

    还有这个……

    While (i++ < threshold) [do something];
    

    或其他一千种特定实现中的任何一个,它们都使用该值并在单个语句中递增它并获得预期的不同结果

    【讨论】:

    • 这似乎非常具体。你确定这是真正的历史原因吗?
    • 没有历史原因——它们有不同的目的。
    • 这些实际上是有趣的变体。 ++i
    • @BenPen,我不明白你在说什么。无论您是在之前还是之后递增,始终只有一个递增。问题是你的阈值是什么,你想要所有值达到并包括阈值,还是只希望那些小于阈值的值......
    • 考虑 i = 0; while (i++
    猜你喜欢
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 2011-06-15
    • 2011-04-18
    • 2021-03-28
    相关资源
    最近更新 更多