Я нашел несколько вопросов по этой конкретной теме, но они касались C ++.
Насколько переносимо приведение -1 к беззнаковому типу?
преобразование -1 в беззнаковые типы
Безопасно ли присвоить -1 беззнаковому int, чтобы получить максимальное значение?
И при чтении ответов казалось вероятным или, по крайней мере, не маловероятным, что это одна из тех вещей, в которых C и C ++ отличаются.
Вопрос простой:
Если я объявляю переменную с unsigned char/short/int/long var или использую любые другие беззнаковые типы, такие как фиксированная ширина, минимальная ширина и т. Д., Будет ли тогда гарантировано, что var = -1 установит var на максимальное значение, которое он может удерживать? Гарантированно ли эта программа печатает Да?
#include <stdio.h>
#include <limits.h>
int main(void) {
unsigned long var = -1;
printf("%s\n", var == ULONG_MAX ? "Yes" : "No");
}
Ответ 1 · рейтинг 7 · KamilCuk
Гарантируется ли, что присвоение -1 беззнаковому типу даст максимальное значение?
да.
Гарантированно ли эта программа печатает Да?
да.
Это преобразование из int -1 в unsigned long. -1 не может быть представлен как unsigned long. Из C11 6.3.1.3p2:
В противном случае, если новый тип является беззнаковым, значение преобразуется путем многократного добавления или вычитания на единицу большего, чем максимальное значение, которое может быть представлено в новом типе, пока значение не окажется в диапазоне нового типа.
поэтому мы добавляем один (ULONG_MAX + 1) к -1 и получаем -1 + (ULONG_MAX + 1) = ULONG_MAX, который находится в диапазоне unsigned long.
Ответ 2 · рейтинг 2 · Lundin
Преобразование из -1 (signed int) в большой беззнаковый тип четко определено в соответствии с C17 6.3.1.3.
В противном случае, если новый тип является беззнаковым, значение преобразуется путем многократного добавления или вычитания на единицу большего, чем максимальное значение, которое может быть представлено в новом типе, пока значение не окажется в диапазоне нового типа 60) sup>.
К нему прилагается полезная записка 60)
- Правила описывают арифметические действия с математическим значением, а не значением данного типа выражения.
Таким образом, учитывая unsigned long var = -1;, значение становится
-1 затем добавляем на единицу больше максимального значения unsigned long
- Значение
-1 + ULONG_MAX+1 = U_LONG_MAX.
Это четко определенное и переносимое поведение. В отличие от преобразований из неподписанного в подписанный, это может вызывать поведение, определяемое реализацией.
Кроме того, это не зависит от формата подписи, поскольку следует использовать математическое значение, а не необработанное двоичное. Если бы вы сделали что-то вроде unsigned long var = (signed long)0xFFFFFFFFF;, то это была бы другая история в случае экзотических / вымышленных систем с дополнением до единицы или величиной со знаком.