语言是否需要 preIncrement (++x) 和 postIncrement (x++)
-
22-09-2019 - |
题
我从来没有见过这个用例 预增量 和 后增量 在实际代码中。我最常看到它们的唯一地方是拼图。
我的观点是,它带来了更多的混乱而不是有用。
- 有没有任何实际的用例场景
这不能通过使用 += 来完成吗
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 语句。
其他提示
如果您根据历史和构思时间来考虑前自增和后自增运算符,它们就更有意义。
回到 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 = x + 1;
....毕竟我没有想到任何用例场景 +=
不能很好地服务 _ = _ + _
反而。
你不小心在这里提出了一个更大的问题,随着时间的推移,这个问题会让你越来越了解。
语言常常会犯错误,在不应该提供“能力”的情况下提供“能力”。IMO,++ 应该是一个独立的声明 仅有的, ,并且绝对 不是 表达式运算符。
尽量牢记以下几点: 目标不是创建代码供有能力的工程师阅读。我们的目标是创建代码,供有能力的工程师在凌晨 3 点筋疲力尽、喝了咖啡因时阅读。
如果工程师对您说“所有代码构造都会给您带来麻烦。你只需要知道你在做什么。”,然后笑着走开,因为他刚刚暴露了自己是问题的一部分。
换句话说,请不要编写如下代码:
a[aIndex++] = b[++bIndex];
您可以在这里找到关于此类事情的有趣对话:为什么要避免在 JavaScript 中增加(“++”)和减少(“--”)运算符?