0

可能重复:
谁能解释这些未定义的行为(i = i++ + ++i,i = i++ 等……)

我和我的朋友正在搞砸,试图想出我们能想到的最糟糕的 for 循环(所以不要告诉我这是糟糕的代码,因为它应该是!)。

我的朋友想出了这个 for 循环:

for (int i = 0; i++ & ++i % (++i % 2) ? --i : i++; i++);

它看起来不错,但由于浮点异常,即使是第一次也无法进入。所以我的第一个想法是模数除以 0。但它似乎没有,因为如果你这样做,它运行良好:

for (int i = 0; i < 100; i++) {
    i++ & ++i % (++i % 2);
}

但这不会:

for (int i = 0; i < 100; i++) {
    i++ & ++i % (++i % 2) ? --i : i++;
}

但它变得陌生。第一种情况运行良好,第二种情况不会:

for (int i = 0; i < 100; i++) {
    i++ & ++i % (++i % 2) ? 0 : 1;
}

for (int i = 0; i < 100; i++) {
    i++ & ++i % (++i % 2) ? 1 : 0; // 1 and 0 switched
}

所以现在我真的对发生的事情感到困惑,但它又变得更奇怪了。如果您将情况与? 0 : 1(运行良好)放入 if 语句中,它会再次引发浮点异常:

for (int i = 0; i < 100; i++) {
    if (i++ & ++i % (++i % 2) ? 0 : 1);
}

我完全迷失了这一点。有人知道这里发生了什么吗?

4

2 回答 2

3

它出错了i++ & ++i。运算符不会对其操作数进行排序,&因此在两边都增加一个会导致未定义的行为。

顺便说一句,这可能是除以零异常,但不一定来自 FPU。

于 2013-02-05T05:14:29.587 回答
1

一般来说,在 C 和 C++ 中的单个表达式中混合这样的多个增量操作是一个坏主意,因为它通常会导致未定义的行为。对于未定义的行为,让事情神秘地改变行为并不奇怪。

另一方面,Java 为所有算术和逻辑运算提供了严格的规范(非 fpstrict 表达式中的浮点指数精度除外)。您可以将所有这些都放入 Java 中(忽略整数不再是有效的布尔表达式这一事实)并让它们给您一个一致的答案,尽管它可能不是您所期望的。

于 2013-02-05T05:07:38.717 回答