我从未见过实际代码中使用前缀递增和后缀递增的用例。我最常见到它们的地方是谜题。
我的意见是,它会引入更多的混乱,而不是有用。
- 是否有任何真正的用例场景需要使用这个操作符?
使用+=操作符不能达到同样的效果吗?
y = x++
y = x
x += 1
我从未见过实际代码中使用前缀递增和后缀递增的用例。我最常见到它们的地方是谜题。
我的意见是,它会引入更多的混乱,而不是有用。
使用+=操作符不能达到同样的效果吗?
y = x++
y = x
x += 1
这只是一种更简洁的写法,对于那些不深入了解C语言的人才会感到困惑 (a)。同样的理由也可以用于替换以下代码:
for (i = 0; i < 10; i++)
printf ("%d\n", i);
使用:
i = 0;
while (i < 10) {
printf ("%d\n", i);
i = i + 1;
}
因为任何一个for
循环都可以用while
循环来实现,或者:
i = 0;
loop: if (i < 10) {
printf ("%d\n", i);
i = i + 1;
goto loop;
}
因为任何循环结构都可以由条件和 goto
构建而成。但是(我希望)你不会这样做,对吧?
(a) 我有时喜欢用简单的语句和副作用来解释这个问题,这样可以使 C 代码更加简洁,通常不会或几乎不会影响可读性。
对于该语句:
y = x++;
语句是将x
赋值给y
,并具有副作用,即之后增加了x
。++x
也是一样的,只是副作用发生在前面。
同样,赋值的副作用是它会被评估为已分配的值,这意味着您可以执行以下操作:
while ((c = getchar()) != -1) count++;
42;
这是一些完全有效但无用的C语句。
for (i = 0; i < 10; i+=1)
? - Anantha Kumaranvoid strcpy(char* a, char* b) { while (*a++ = *b++) ; }
- Travis Gockel如果您考虑到历史和它们的发明时间,前缀和后缀递增运算符会更有意义。
在C语言基本上是PDP-11机器的高级汇编语言</ flamebait>
时代,远在我们现在拥有的优化编译器之前,有一些常见的习惯用法是后缀递增运算符非常适合的。比如:
char* strcpy(char* src, char* dest)
{
/* highly simplified version and likely not compileable as-is */
while (*dest++ = *src++);
return dest;
}
这段代码生成了PDP-11(或其他)机器语言代码,大量使用了底层寻址模式(如相对直接和相对间接),其中包含了这些前后增减操作。
那么回答你的问题:现在的编程语言是否“需要”这些呢?当然不需要。可以证明,在计算方面,你只需要非常少的指令。更有趣的问题是:“这些功能是否可取?”对此,我的回答是“是的,但有限制条件”。
以你的例子为例:
y = x;
x += 1;
对比。
y = x++;
x[f(y)][g(z)] += 10
的代码实际上比 x[f(y)][g(z)] = x[f(y)][g(z)] + 10
更高效,因为编译器在第一种情况下只需要评估一次 x[f(y)][g(z)]
,但在第二种情况下可能需要评估两次。 - Gabex[f(y)][g(z)]
优化为只评估一次。这种优化是可能的,但远非保证!如果f和g是外部函数,编译器别无选择,只能评估两次。 - Gabea += b;
和 a = a + b;
的一个优点是,如果两者都可以重载(如在 C++ 中),前者可以表示“追加”,而后者则设置了一个全新的值。不过,这两种语句的最终结果在实践中几乎相同,差别主要在于效率。因此,合理的代码应该使这两种语句的最终结果基本相同。 - cHaoa+=b
和a=a+b
提供不同的能力)并不是一个“加分项”,无论哪个类实现它。这违背了语言的基本原则(由于内置算术类型已经很好地理解了),并且会对阅读代码的模式识别造成极大的破坏。C++的粉丝们毫无疑问会对此进行负面评价,但在我看来,这是因为混淆了“能做”和“应该做”的编程概念,在C++中这种情况太常见了。 - user4229245你在这里无意中提出了一个更大的问题,随着岁月(几十年)的流逝,这个问题会变得越来越明显。
语言经常犯错误,当它们不应该提供“能力”时。在我看来,++应该是一个独立的语句,而绝对不是一个表达式运算符。
请尽量牢记以下内容:目标不是为有能力的工程师创建可读的代码。目标是为那些在凌晨3点精疲力尽、兴奋不已的有能力的工程师创建可读的代码。
如果一个工程师对你说:“所有的代码结构都可能会让你陷入麻烦。你只需要知道你在做什么。”,那么笑着走开吧,因为他刚刚暴露了自己是问题的一部分。
换句话说,请永远不要编写像这样的任何代码:
a[aIndex++] = b[++bIndex];
你可以在这里找到一段关于这种事情的有趣对话: 为什么要避免在JavaScript中使用递增(“++”)和递减(“--”)运算符?