Таинственное исключение с плавающей точкой

Возможный дубликат:
Может ли кто-нибудь объяснить это неопределенное поведение (i = i ++ + ++ i, i = i ++ и т. Д.)

Мой друг и я бездельничали, пытаясь придумать наихудшие циклы, о которых мы могли подумать (поэтому не говорите мне, что это ужасный код, потому что он должен быть!).

Мой друг придумал это для цикла:

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);
}

Я полностью потерян в этом. У кого-нибудь есть идеи, что здесь происходит?

0

Решение

Это идет не так в i++ & ++i, & Оператор не упорядочивает свои операнды, поэтому приращение с обеих сторон приводит к неопределенному поведению.

Кстати, это, вероятно, деление на ноль исключение, но не обязательно из FPU.

3

Другие решения

В общем, плохая идея смешивать несколько операций приращения, подобных этой, в одном выражении в C и C ++, потому что это обычно приводит к неопределенному поведению. С неопределенным поведением, таинственное изменение поведения не удивительно.

Java, с другой стороны, обеспечивает жесткую спецификацию для всех арифметических и логических операций (за исключением точности показателей с плавающей запятой в выражениях, не относящихся к fpstrict). Вы можете поместить все это в Java (игнорируя тот факт, что целые числа больше не являются допустимыми логическими выражениями), и дать им последовательный ответ, хотя он может не соответствовать вашим ожиданиям.

1

По вопросам рекламы [email protected]