"не надо так"… Я прямо даже и не знаю, как сказать.
А в сях есть способ написать
dword r = a — b;
if (was_overflow) r=0;
чтоб скомпилировалось в проверку флага после вычитания?
Я не знаю, как другие бы сделали это лаконично, я бы сперва числа сравнил друг с другом перед вычитанием. Ради интереса, я сейчас изучаю Rust, и стал на эти проблемы чаще обращать своё внимание.
Интересно, а
dword r = a-b;
if (b > a) return 0; else return r;
соптимизируется на ASM уровне само или нет?
GCC (O2):
mov eax, edi
mov edx, 0
sub eax, esi
cmp edi, esi
cmovb eax, edx
ret
Clang (O2):
xor eax, eax
sub edi, esi
cmovae/cmovge eax, edi (ae for uint32_t, ge for int32_t)
ret
Остальные компиляторы можете попробовать по аналогии там же.
ни один из них не свернулся в sub + jo/jno…
При этом вариант с __builtin_sub_overflow сворачивается хорошо
godbolt.org/z/sq63d3
subs w8, w0, w1 # вычесть из w0 (a) w1 (b), положить результат в w8 (a-b)
csel w0, wzr, w8, lo # сравнить содержимое wzr (ноль) с w8 (a-b), если строго меньше, то положить в w0 (возвращаемое из функции значение) wzr (ноль), иначе w8 (a-b)
ret
Что-то GCC/arm с -O3 мне даже вариант с builtin выдаёт что-то странное.
то есть да, clang делает хорошо :)
я ступил и смотрел только разные варинты записи для GCC.
А вот компилятор Rust'а предлагает, и в 99% случаев его предложения правильные. Почему? Потому что компилятор ууууумный. А язык правильный.
Последняя Mother of All Errors, которую я словил, добавив в невинную структуру ещё одно поле состояла из ~10 строчек, в которых мне объяснялось, что из-за этого поля (совсем в другом месте, совсем другую структуру) нельзя больше безопасно передавать между тредами. Причём в ошибке мне даже сказали, что можно ещё в одном месте заменить Fn на FnOnce, и тогда будет хорошо. Я сделал — и стало хорошо.
Ну, справедливости ради, многое из того, что проверяет PVS-studio и при этом не завязано на язык (вроде одинаковых веток в условном операторе), сейчас не ловят ни компилятор, ни Clippy, так что есть куда расти.
Рассмотрим ошибку, которую я разбирал в статье
Ошибка лютая, конечно.
Прикольно, но бессмысленно ;). Анализатор убрал код, который с точки зрения языка C++ является лишним.
А если как-то так поставить вопрос, чтобы это служило индикатором некооректной логики?
некооректнойнекорректной
Шикарный пример, спасибо.
Почему PVS-Studio не предлагает автоматические правки кода