- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
template <class T>
T checked_signed_add(T a, T b) {
if (a >= 0) {
if (b >= 0 && std::numeric_limits<T>::max() - a < b)
throw std::runtime_error("Integer overflow");
} else {
if (b < 0 && std::numeric_limits<T>::min() - a > b)
throw std::runtime_error("Integer overflow");
}
return a + b;
}
absolut 06.02.2015 14:21 # 0
или какой тут был посыл, Борманд?
bormand 06.02.2015 14:50 # +5
pushistayapodmyshka 06.02.2015 15:25 # +1
Я вот на шарю в этих ваших крестах, и потому этот пример выглядит для меня как очередной троллейбус.
kegdan 06.02.2015 16:36 # +3
kegdan 06.02.2015 16:31 # 0
roman-kashitsyn 06.02.2015 16:32 # +1
kegdan 06.02.2015 16:37 # 0
guest 06.02.2015 22:49 # 0
Qwertiy 06.02.2015 23:03 # 0
Но вроде компиляторы, в отличие от стандарта, объявляют как undefined value, а не undefined behavior.
bormand 07.02.2015 10:59 # 0
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.
Вообще говоря, у проца может быть железная проверка на overflow. И это сложение тупо вызовет прерывание и ось убьёт процесс нахуй, как и при делении на ноль... Поэтому тут и не undefined value, а именно behavior.
Qwertiy 07.02.2015 14:55 # 0
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
Signed integer overflow: If arithmetic on an 'int' type (for example) overflows, the result is undefined. One example is that "INT_MAX+1" is not guaranteed to be INT_MIN. This behavior enables certain classes of optimizations that are important for some code.
Both Clang and GCC accept the "-fwrapv" flag which forces the compiler to treat signed integer overflow as defined (other than divide of INT_MIN by -1).
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.html
2. Arithmetic that operates on undefined values is considered to produce a undefined value instead of producing undefined behavior. The distinction is that undefined values can't format your hard drive or produce other undesirable effects. A useful refinement happens in cases where the arithmetic would produce the same output bits given any possible instance of the undefined value. For example, the optimizer assumes that the result of "undef & 1" has zeros for its top bits, treating only the low bit as undefined. This means that ((undef & 1) >> 1) is defined to be 0 in LLVM, not undefined.
3. Arithmetic that dynamically executes an undefined operation (such as a signed integer overflow) generates a logical trap value which poisons any computation based on it, but that does not destroy your entire program. This means that logic downstream from the undefined operation may be affected, but that your entire program isn't destroyed. This is why the optimizer ends up deleting code that operates on uninitialized variables, for example.
guest 07.02.2015 15:48 # −1
Так-то можно вообще стандарт не читать, проверить на тестовом примере чтоб работало и ладно.
Qwertiy 07.02.2015 19:08 # 0
kipar 09.02.2015 13:39 # 0
bormand 09.02.2015 14:31 # 0
Вот именно! Поэтому не надо читать про поведение при UB и не надо тестировать поведение при UB. От этого нет никакой пользы, сплошной вред и ложные надежды. Нужно просто писать код так, чтобы в нём не было UB.
absolut 09.02.2015 15:15 # +3
т.е. не на плюсах
Vasiliy 09.02.2015 15:32 # 0
Vindicar 09.02.2015 10:20 # +1
bormand 09.02.2015 11:09 # +1
bormand 07.02.2015 11:01 # 0
-2 + (-3) = -5. Сумма меньше любого слагаемого. Переполнение, однако.
kegdan 07.02.2015 11:32 # 0
1024-- 07.02.2015 11:43 # 0
На основе Функции Борманда построить простой класс, хранящий unsigned int и использующий std::numeric_limits<unsigned int>::max() в качестве значения "NaN". Реализовать все нужные опереции и is_nan (переполнение и прочая питушня - NaN; каст NaN в unsigned int - exception). А желающие сами напишут себе знаковые инты и плавающих питунцов на основе BormandUnsigned.
bormand 07.02.2015 12:03 # 0
Xom94ok 07.02.2015 13:29 # +1
Lure Of Chaos 07.02.2015 22:38 # +3
Vindicar 09.02.2015 10:26 # −1
(a+b)/2 ошибется при переполнении
a/2 + b/2 ошибется при a=1 и b=1
a + (b-a)/2 получится фигня если b < a
TarasB 09.02.2015 10:34 # 0
bormand 09.02.2015 11:10 # +1
Vindicar'у понравится: есть ли хоть что-нибудь в этом языке что не было бы UB? ;)
defecate-plusplus 09.02.2015 11:17 # 0
так что можно замутить на макросах выяснение, какое представление используется для знаковых целых (т.к. компилятор уже всё знает)
bormand 09.02.2015 11:32 # 0
49) A positional representation for integers that uses the binary digits 0 and 1, in which the values represented by successive bits are additive, begin
with 1, and are multiplied by successive integral power of 2, except perhaps for the bit with the highest position. (Adapted from the American National Dictionary for Information Processing Systems.)
Т.е. все эти 3 варианта они просто для примера привели. Сложно будет придумать какое-то новое представление. Но если вдруг придумаю - имею полное право юзать, стандарт разрешает.
defecate-plusplus 09.02.2015 11:38 # 0
пф, есть коды с двумя знаковыми битами
как раз чтобы +/- переполнение отслеживать
на x86 в качестве второго знакового бита можно использовать OF или как там его
bormand 09.02.2015 11:42 # 0
SSDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD
Тогда даже без OF можно переполнение поймать и обработать...
P.S. Ну т.е. в итоге всё-таки нельзя полагаться на то, что извращённая фантазия разрабов компилятора ограничена теми тремя представлениями...
roman-kashitsyn 09.02.2015 11:15 # 0
Люр говорит о бинарном поиске, там инвариант a <= b. Я лично пишу в бинарном поиске a + (b - a) / 2.