Возможный дубликат:
Может ли кто-нибудь объяснить это неопределенное поведение (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);
}
Я полностью потерян в этом. У кого-нибудь есть идеи, что здесь происходит?
Это идет не так в i++ & ++i
, &
Оператор не упорядочивает свои операнды, поэтому приращение с обеих сторон приводит к неопределенному поведению.
Кстати, это, вероятно, деление на ноль исключение, но не обязательно из FPU.
В общем, плохая идея смешивать несколько операций приращения, подобных этой, в одном выражении в C и C ++, потому что это обычно приводит к неопределенному поведению. С неопределенным поведением, таинственное изменение поведения не удивительно.
Java, с другой стороны, обеспечивает жесткую спецификацию для всех арифметических и логических операций (за исключением точности показателей с плавающей запятой в выражениях, не относящихся к fpstrict). Вы можете поместить все это в Java (игнорируя тот факт, что целые числа больше не являются допустимыми логическими выражениями), и дать им последовательный ответ, хотя он может не соответствовать вашим ожиданиям.