-1

我认为下面的代码是邪恶的,但它可以在没有任何警告的情况下编译。

int f(int n)
{
    return n + 1;
}

int n = 0;
n = f(n++) + f(++n);

我只是想知道为什么神圣标准不弃用这样的运营商?

我想可能有两个原因:

一种可能是为了向后兼容;

另一个可能是在某些情况下,这些运算符非常有用。

如果后者是真的,你能给我举一些例子吗?谢谢。

4

3 回答 3

7

它不仅仅是邪恶,它是 Undefined Behaviour™。这就是为什么所有理智的人都禁止这种用途。

向后兼容性肯定是问题的一半——增量和减量无处不在。它们对于迭代器和其他东西也很有用。

底线是,C++ 从来没有阻止过你在自己的脚下开枪。这只是一个例子。C++ 不会仅仅因为它们可能是坏的而禁止可能是好的东西。不滥用它们是你的问题。

于 2013-09-19T14:33:00.113 回答
1

从 C 和/或 C++中删除这些++--运算符肯定会破坏很多代码 - 事实上我怀疑,如果你删除这两个运算符,几乎每个现有的源文件都会停止编译。

正确使用时它们非常有用——只要你不在同一个变量的两边都使用它,你会没事的。

此代码不会编译,但添加括号以使其(++n)++正确编译 - 但 g++ 会发出警告“对 'n' 的操作可能未定义”。

如果我们去掉++and--操作符,你希望如何编写一个通用的 for-lopp:

for(int i = 0; i < 100; i++)

像这样:

for(int i = 0; i < 100; i = i + 1)

或者

for(int i = 0; i < 100; i += 1)

禁止在 C 和 C++ 中可能被滥用的所有内容几乎会使该语言变得毫无用处 - 并且肯定会使该语言完全无用或至少阻止许多有效的使用。这就像禁止使用刀具,因为人们可以使用它们(并且确实已经使用它们)做坏事。但如果你想切面包、肉或蔬菜,他们确实为此目的制作了非常方便的工具。

于 2013-09-19T14:36:08.537 回答
0

我只是想知道为什么神圣标准不弃用这样的运营商?

因为这是完全有效的代码,但它调用了未指定的行为,因为未指定 C 表达式中操作数的求值顺序。代码中唯一的问题是由程序员创建的,他编写的代码依赖于未指定的行为。对程序员进行语言培训不是 C 标准的任务。

(这不是未定义的行为。请参阅 C11 6.5.2.2。在函数调用和实际调用中的函数指示符和实际参数的评估之间存在一个序列点。如果不是每个函数参数评估之后的序列点,这将是未定义的行为,因为您不能在没有序列点的操作中两次修改相同的变量。)

一种可能是为了向后兼容;

No. C 一直有未指定的操作数求值顺序。此代码从标准前的 K&R 代码一直到 C11 的工作方式相同。

另一个可能是在某些情况下,这些运算符非常有用。

不,您发布的代码在任何情况下都没有用。它被混淆了,可以用更好的方式编写,以更安全、更易读的方式实现相同的功能和相同的机器代码。例如:

n++;
n = f(n) + f(n);
n++;
于 2013-09-19T14:56:57.543 回答