2015-06-20 6 views
2

Предположим, что я объявил следующие переменные:Является ли хорошей практикой использовать long int, чтобы избежать переполнения?

some_dataType a,b,c; //a,b,c are positive 
int res; 
res=a+b-c; 

И я была предоставлена ​​информация о том, что переменная res не может пересечь предел целое. Просто, чтобы избежать переполнения из выражения a+b в a+b-c У меня после Options-

  1. объявить, Ь, с тех пор ИНТ
  2. (a-c) + б
  3. (long int) (а + Ьс) // или какой-либо другой литье под давлением

Мой вопрос в том, какая из перечисленных выше является хорошей практикой. Кроме того, чтобы избежать всего этого, я предпочитаю делать вариант 1. Но он может увеличить объем памяти программы (не для этой программы, а для больших приложений).
Предположение: долго ИНТ больше ИНТ Спасибо @Retired Ninja

+2

Одна переменная не увеличит объем памяти вашей программы каким-либо значимым образом, и поскольку ваш пример неполный, похоже, что это будет переменная в стеке. Вы также делаете предположение, что long больше, чем int, и этого может и не быть. –

+0

Вариант 3 бессмыслен. Я бы выбрал вариант 2, а не потому, что 'long' увеличит использование вашей памяти (это не будет иметь никакого смысла), но поскольку' long' не обязательно делает то, что вы хотите (он может иметь тот же размер, что и ' int'). –

+1

Вариант 2 все еще может быть неудачным. Возьмите 'a = INT_MAX, b = 2, c = 1'. – chris

ответ

4

Там нет простого, вообще, переносимый способ избежать целочисленного переполнения.

Использование более широкого целочисленного типа не является общим решением, поскольку нет гарантии, что существует более широкий целочисленный тип. Для типов int и long очень распространены одинаковые размеры на некоторых системах. 32-разрядные системы обычно составляют как int, так и long 32 бита; даже некоторые 64-битные системы делают то же самое. И некоторые 64-битные системы делают как int, так и long 64 бит.

Вы писали:

И я была предоставлена ​​информация о том, что переменная res не может пересечь предел целое.

Лучше быть осторожным с терминологией. Хотя имя типа int, очевидно, является аббревиатурой слова «целое число», слова не являются синонимами. В C и C++ int является одним из нескольких целых чисел типов; другие включают unsigned char и long long.

Предположительно, что вы имеете в виду, что значение res не должны находиться за пределами диапазона типа int, который INT_MIN к INT_MAX.

Если вы используете long long для получения результата, вероятно, вы сможете избежать переполнения; вы можете сравнить результат с значениями INT_MIN и INT_MAX и предпринять любые корректирующие действия, если это вне пределов досягаемости. Но все же возможно, что и int, и long long будут 64 бит. То, что вы делаете с этим, зависит от того, насколько портативен ваш код.

Вы не можете безопасно проверить, не произошло ли превышение знака целого сложения или вычитания после факта. Переполнение в подписанной арифметике вызывает неопределенное поведение.Как правило, результат обертывается, но в принципе ваша программа может потерпеть крах, прежде чем у вас будет возможность изучить результат.

Некоторые компиляторы могут предоставлять функции, которые выполняют безопасную подписанную арифметику и сообщают вам, произошло ли переполнение. Обратитесь к документации вашего компилятора.

Есть способы проверить операнды перед выполнением операции. Они сложны, и я слишком ленив, чтобы работать над деталями, но вкратце:

  • Если операнды + имеют противоположные знаки, или если один из операндов имеет 0, добавление является безопасным.
  • Если оба операнда положительны, добавление безопасно, если x не превышает INT_MAX - y.
  • Если оба операнда отрицательные, добавление безопасно, если y составляет не менее INT_MIN - y.

Я не гарантирую, что приведенное выше полностью верно * Я просто написал это с головы), но в большинстве случаев это, вероятно, больше усилий, чем того стоит.

0

Доверяй, но проверяй:

assert(a > 0); 
assert(b > 0); 
assert(c > 0); 
assert((long)a - (long)c + (long)b <= INT_MAX); 

int res = a - c + b; 
+1

Я согласен с настроением, но вы вычисляете одно и то же значение несколько раз и не обнаруживаете переполнение. Также проблема должна быть обнаружена и обработана в коде выпуска, а не в утверждениях. –

+0

@KennyOstrom Вы совершенно правы, конечно. Мой код - это просто демо, единственная цель которого - подчеркнуть, что то, что заявлено («что-то всегда в таком диапазоне»), это одно, а на самом деле часто бывает другое. – dlask

Смежные вопросы