Вы разрабатываете графический интерфейс для игры. У вас уже есть кнопочки, панельки, иконки. Все отлично. И вот вы решаете, чтоб интерфейс ощущался интереснее, реализовать анимацию для check box элемента -- при нажатии для снятия галочки, check_box элемент будет красиво отъезжать в сторону где-то на 30% своей ширины.
У вас были подобные структуры и функции
struct Element {
size_t width; // original non scaled width
...
};
using ElementID = uint64_t; // you are using smart component system that uses IDs to refer to elements
// Positions in OpenGL/DirectX/Vulkan worlds are floats
struct Offset {
float x;
float y;
};
size_t get_width(ElementID);
float screen_scale();
void move_by(ElementID, Offset);
И вы добавили свою
void on_unchecked(ElementID el) {
auto w = get_width(el);
move_by(el, Offset {
-w * screen_scale() * 0.3f,
0.0f
});
}
Ваш check_box имел ширину 50 пикселей. Вы запустили тест... И элемент улетел за пределы экрана!
Вы пошли смотреть логи и обнаружили
Offset: 5.5340234e+18 0
Как же так?! Неопределенное поведение?
Нет. Вполне определенное.
Всему виной унарный минус, который мы случайно применили к беззнаковой переменной.
For unsigned a, the value of -a is 2^N − a, where N is the number of bits after promotion.
Это очень злобная ошибка, которую не диагностируют Clang и GCC с флагами -Wall -Wextra -Wpedantic
;
MSVC же имеет такую диагностику
Статические анализаторы, например, PVS-studio также могут найти ошибку.
В более современных языках программирования применение унарного минуса к беззнаковым значениям чаще всего не компилируется. Так, например, сделано в Rust, Zig и в Kotlin.