diff --git a/numeric/overflow.md b/numeric/overflow.md index c8909d5..a08c5fe 100644 --- a/numeric/overflow.md +++ b/numeric/overflow.md @@ -31,7 +31,21 @@ if (x > 0 && a > 0 && x + a <= 0) { Но, увы, это неопреденной поведение. И компилятор имеет полное право [выкинуть](https://godbolt.org/z/dhs83T) такую проверку. -Корректные проверки куда сложнее и тяжелее. +Искусственный пример может быть недостаточно убедительным, так что обратим внимание на следущую, вполне серьезную, функцию вычисления полиномиального хэша строки: +```C++ +int hash_code(std::string s) { + int h = 13; + for (char c : s) { + h += h * 27752 + c; + } + if (h < 0) h += std::numeric_limits::max(); + return h; +} +``` +Функция, которая никогда не должна, по задумке, возвращать отрицательные числа, таки [выдает](https://godbolt.org/z/4v139E) отрицательное число! Из-за неопределенного поведения и бессмысленной с точки зрения компилятора проверки. + + +Корректные проверки переполнения куда сложнее и тяжелее. Так, для C++20, безопасный обобщенный код арифметических операций над целыми знаковыми числами мог бы выглядеть так @@ -199,3 +213,4 @@ x *= x; // переписывается как x = x * x; ### Полезные ссылки 1. https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow 2. https://stackoverflow.com/a/46073296 +3. https://habr.com/ru/post/307702/