Ответ 1
Перечисленное целочисленное переполнение дает поведение undefined. Таким образом, компилятор имеет свободное владение, чтобы реализовать этот случай по своему усмотрению.
Мне пришлось закодировать некоторые процедуры проверки, и они, похоже, ведут себя по-другому, если вы используете -O0, -O1, -O2 или -O3.
Ниже я создал минимальный пример, который отлично подходит для -O0 и -O1. Но с использованием -O2 или -O3 поведение изменилось. В случае -O0 и -O1 for-loop увеличивает значение целого числа, и первый раз, когда он достигает максимума, происходит переполнение и запускается процедура проверки. В другом случае for-loop никогда не прерывается, хотя целое число становится отрицательным.
#include <iostream>
inline bool check(const int i) {
if (i < 0)
return false;
else
return true;
}
int main() {
for (int i = 0;; i += 50000000) {
std::cout << i << std::endl;
const bool succ = check(i);
if (succ == false) {
std::cout << "Overflow: " << i << std::endl;
break;
}
}
return 0;
}
Почему компилятор разрешил оптимизировать это?
Пытаясь использовать gcc, clang и icc, только icc делает это правильно во всех вариантах оптимизации, другие два не сделали.
Перечисленное целочисленное переполнение дает поведение undefined. Таким образом, компилятор имеет свободное владение, чтобы реализовать этот случай по своему усмотрению.