Привет, Хабр! Меня зовут Владимир, я работаю в VK Карты. Хочу рассказать про случай, который недавно произошёл у нас в подразделении. Он кажется достаточно типичным и может быть интересен другим программистам. Нам, программистам на C++, не привыкать, что даже самый безобидный код может таить в себе сюрпризы. Рассмотрим пример: Он полон сюрпризов! Каких? Короткий ответ: значение signed_offset не определено стандартом и зависит от реализации. Но это далеко не все неожиданности в этом коде. Статья как раз о них. Давайте сначала разберемся с тем, что возвращает -width. Это может прозвучать неожиданно, но тип, возвращаемый -width, это uint32_t. И это не опечатка. То есть если унарный минус применить к неотрицательному числу, то в результате получим опять же неотрицательное число. Давайте разберёмся, как такое могло получиться и чему будет равен результат -width. Если выполнить такой код: То результат сообщит нам, что у переменной offset тип uint32_t, а значение — 4 294 967 289. Чтобы понять, что здесь происходит, достаточно взглянуть на раздел 8.3.1.8 стандарта C++ 17. Из него следует, что тип, возвращаемый -width, будет такой же, как и тип width. А значение, которое возвратит -width, это 232 минус значение width. То есть 4 294 967 296 — 7 = 4 294 967 289. 232 потому, что 32 — это количество бит, необходимое для размещения переменной типа uint32_t. Уточню относительно записи auto offset = -width;. В некоторых случаях у auto есть особые правила вывода типа, и чтобы вывелся в точности тип значения, возвращаемого выражением, лучше использовать decltype(auto). Но в этом случае auto и decltype(auto) дадут аналогичные результаты, так что я решил не усложнять. Итак, пока что мы получили определённое стандартом значение, которое возвращает унарный минус (-width). Это 4 294 967 289. Однако в начале я писал, что значение переменной signed_offset типа int32_t будет не определено. Проблема тут в конвертации беззнакового типа uint32_t в знаковый int32_t. Рассмотрим пример: За конвертацию целых типов отвечает раздел стандарта 7.8, в нашем случае, это 7.8.3. Этот пункт, говорит, что если беззнаковый тип поместится в соответствующем знаковом, то всё будет работать предсказуемо. Иными словами, переменной signed_positive_offset будет присвоено значение 7. А вот если значение беззнакового типа не помещается в знаковом, то присвоенное знаковому типу значение зависит от реализации. Обратимся к примеру в самом начале статьи: Как мы выяснили выше, -width вернёт значение 4 294 967 289 типа uint32_t. А оно не поместится в int32_t. Соответственно, значение signed_offset будет не определено. Отмечу, что согласно стандарту это допустимая запись, не приводящая к неопределенному поведению. То есть код допустим, но значение в signed_offset после его исполнения может быть любым. Если скомпилировать и запустить этот пример, то с большой долей вероятности в signed_offset окажется -7. Так реагирует Clang 13.1.6 на MacOS. Но это реакция на переполнение знакового целого числа. А с точки зрения стандарта в signed_offset может быть любое значение. Отмечу, что стандарт по-разному относится к переполнению знаковых и беззнаковых типов. При присвоении слишком большого значения знаковому типу мы получаем поведение, зависящее от реализации. Этот случай мы подробно рассмотрели выше. При присвоении слишком большого значения беззнаковому типу мы получим вполне определённое и гарантированное стандартом поведение, согласно разделу 7.8.2. Правило такое: если мы хотим присвоить число big_number переменной unsigned_offset беззнакового типа some_unsigned_type, то результатом этой операции будет число big_number по модулю 2n, где n — количество бит,  необходимое для хранения типа some_unsigned_type. Звучит запутано, но на самом деле тут всё предельно просто. Достаточно взглянуть на пример: unsigned_offset будет равно 7, потому что размер uint32_t — 32 бита. 232 равно 4 294 967 296, а 4 294 967 296 + 4 294 967 296 по модулю 4 294 967 296 будет равно 0. Выходит результат 7. Рекомендую обращать внимание на неявные переполнения беззнаковых типов. В частности, стоит избегать применения унарного минуса к беззнаковым типам. Если же нужно, чтобы код выше был выполнен, то можно написать, например, так: Во всех рассуждениях я преимущественно писал про uint32_t и int32_t. Однако эти рассуждения верны соответственно для всех знаковых и беззнаковых типов.  Стандарт C++17 P.S. Хочу кое-что уточнить. То что я писал выше относится к стандарту C++17. В C++20 приняли "two's complement". Это раздел 6.8.1, параграф 3. То есть код из начала статьи: должен всегда работать одинаково в C++20, и signed_offset должно быть -7. В C++17 значение signed_offset не определено.