C 中预自增运算符的作用是什么?
What purpose does the pre-increment operator serve in C?
在 C 及其许多派生语言中,i++
递增 i
并求值为 i
递增之前的值,而 ++i
递增 i
并计算 i
在 之后的值。
我可以看到特定增量运算符的推理;当时许多处理器都有一个特殊的增量操作码,它比加法快,并且从概念上讲 "increment" 与 "add," 的想法不同,理论上以不同的方式编写它们可能会使代码更具可读性。
我不明白的是需要预增量运算符。不能这样写有什么实际用处吗?
#This...
x = i++;
#becomes this:
x = i;
++i;
是否有我不知道的历史原因?您是否无法 "throw away" 原始版本的 C 中运算符的 return 值?
例如,您可以这样做
While (++i < threshold) [do something];
还有这个……
While (i++ < threshold) [do something];
或其他一千种既使用该值又在单个语句中递增它并获得预期的不同结果的特定实现中的任何一个
一个原因是它允许生成高效的代码,而无需在编译器中进行任何花哨的优化阶段,前提是程序员知道他(或她)在做什么。例如,当将字符从一个缓冲区复制到另一个缓冲区时,您可能有:
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
我忘记了实际的操作码。编译器不包含优化阶段,但它生成的代码非常紧凑,前提是您了解编译器和机器架构。它可以这样做是因为硬件架构对地址寄存器和通用寄存器都有预递减和 post-递增寻址模式。据我所知,没有预递增和 post-递减寻址模式,但没有这些你也能过得去。
我相信最初开发C的DEC小型机就有这样的寻址方式。我工作的机器不是 DEC 制造的,但架构非常相似。
为编译器计划了一个优化阶段。然而,它主要由系统程序员使用,当他们看到生成的代码有多好时,优化阶段的实现被悄悄搁置。
C 设计的全部基本原理是允许创建简单且可移植的编译器,这些编译器将生成相当高效的代码,而中间代码优化最少(或没有)。出于这个原因,递增和递减运算符以及复合赋值运算符在早期 C 编译器生成紧凑高效的代码中发挥了重要作用。它们不仅仅是 Niklaus Wirth 等人所建议的语法糖
在 C 及其许多派生语言中,i++
递增 i
并求值为 i
递增之前的值,而 ++i
递增 i
并计算 i
在 之后的值。
我可以看到特定增量运算符的推理;当时许多处理器都有一个特殊的增量操作码,它比加法快,并且从概念上讲 "increment" 与 "add," 的想法不同,理论上以不同的方式编写它们可能会使代码更具可读性。
我不明白的是需要预增量运算符。不能这样写有什么实际用处吗?
#This...
x = i++;
#becomes this:
x = i;
++i;
是否有我不知道的历史原因?您是否无法 "throw away" 原始版本的 C 中运算符的 return 值?
例如,您可以这样做
While (++i < threshold) [do something];
还有这个……
While (i++ < threshold) [do something];
或其他一千种既使用该值又在单个语句中递增它并获得预期的不同结果的特定实现中的任何一个
一个原因是它允许生成高效的代码,而无需在编译器中进行任何花哨的优化阶段,前提是程序员知道他(或她)在做什么。例如,当将字符从一个缓冲区复制到另一个缓冲区时,您可能有:
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
我忘记了实际的操作码。编译器不包含优化阶段,但它生成的代码非常紧凑,前提是您了解编译器和机器架构。它可以这样做是因为硬件架构对地址寄存器和通用寄存器都有预递减和 post-递增寻址模式。据我所知,没有预递增和 post-递减寻址模式,但没有这些你也能过得去。
我相信最初开发C的DEC小型机就有这样的寻址方式。我工作的机器不是 DEC 制造的,但架构非常相似。
为编译器计划了一个优化阶段。然而,它主要由系统程序员使用,当他们看到生成的代码有多好时,优化阶段的实现被悄悄搁置。
C 设计的全部基本原理是允许创建简单且可移植的编译器,这些编译器将生成相当高效的代码,而中间代码优化最少(或没有)。出于这个原因,递增和递减运算符以及复合赋值运算符在早期 C 编译器生成紧凑高效的代码中发挥了重要作用。它们不仅仅是 Niklaus Wirth 等人所建议的语法糖