Мои вопросы делятся на три части
Вопрос 1
Рассмотрим приведенный ниже код,
#include <iostream>
using namespace std;
int main( int argc, char *argv[])
{
const int v = 50;
int i = 0X7FFFFFFF;
cout<<(i + v)<<endl;
if ( i + v < i )
{
cout<<"Number is negative"<<endl;
}
else
{
cout<<"Number is positive"<<endl;
}
return 0;
}
Не используются конкретные параметры оптимизации компилятора или используется флаг O. Это основная команда компиляции g++ -o test main.cpp используется для формирования исполняемого файла.
По-видимому, очень простой код имеет странное поведение в 64-разрядной ОС SUSE, gcc версии 4.1.2. Ожидаемый вывод: "Число отрицательно", вместо этого только в 64-разрядной ОС SUSE, выход будет "Число положительное".
После некоторого анализа и выполнения "disass" кода я обнаружил, что компилятор оптимизирован в следующем формате -
- Так как я одинаково по обе стороны сравнения, его нельзя изменить в том же выражении, удалите 'i' из уравнения.
- Теперь сравнение приводит к
if ( v < 0 )
, где v является константой положительной. Поэтому во время самой компиляции в регистр добавляется адрес функции cout part else. Инструкции cmp/jmp не найдены.
Я вижу, что поведение только в gcc 4.1.2 SUSE 10. При попытке в AIX 5.1/5.3 и HP IA64 результат будет таким, как ожидалось.
Является ли приведенная выше оптимизация действительной?
Или, используется механизм переполнения для int не допустимый прецедент?
Вопрос 2
Теперь, когда я изменяю условный оператор от if (i + v < i)
до if ( (i + v) < i )
даже тогда, поведение такое же, это, по крайней мере, я лично не соглашусь, поскольку дополнительные скобки предоставлены, я ожидаю, что компилятор создаст временную встроенную переменную типа и они сравнивают, таким образом, сводят на нет оптимизацию.
Вопрос 3
Предположим, у меня есть огромная база кода, я переношу мою версию компилятора, такая ошибка/оптимизация может привести к хаосу в моем поведении системы. Конечно, с точки зрения бизнеса, очень сложно проверить все строки кода снова только из-за обновления компилятора.
Я думаю, что для всех практических целей подобные ошибки очень трудно поймать (во время обновления) и неизменно будут просачиваться на производственную площадку.
Может ли кто-нибудь предложить какой-либо возможный способ обеспечить, чтобы эта ошибка/оптимизация не влияла на мою существующую системную/кодовую базу?
PS:
- Когда const для v удаляется из кода, оптимизация не выполняется компилятором.
- Я считаю, что отлично использовать механизм переполнения, чтобы узнать, имеет ли переменная значение MAX-50 (в моем случае).
Update (1)
Чего я хочу достичь? переменная я будет счетчиком (вроде syncID). Если я выполняю операцию в автономном режиме (50 операций), то во время запуска я хотел бы reset мой счетчик. Для этого я проверяю значение границы (до reset it), а не добавляю его вслепую.
Я не уверен, полагаюсь ли я на аппаратную реализацию. Я знаю, что 0X7FFFFFFF является максимальным положительным значением. Все, что я делаю, добавляет к этому значение, я ожидаю, что возвращаемое значение будет отрицательным. Я не думаю, что эта логика имеет какое-то отношение к аппаратной реализации.
В любом случае, спасибо за ваш вклад.
Update (2)
Большая часть входной станции указывает, что я полагаюсь на поведение более низкого уровня при проверке переполнения. У меня есть один вопрос относительно того же,
- Если это так, для unsigned int как проверить и reset значение во время переполнения или переполнения? например, если v = 10, я = 0X7FFFFFFE, я хочу reset я = 9. Аналогично для underflow?
Я не смог бы этого сделать, если не проверю отрицательность числа. Поэтому я утверждаю, что int должен возвращать отрицательное число, когда значение добавляется в + MAX_INT.
Пожалуйста, дайте мне знать ваши данные.