Строго говоря, согласно стандарту C, требуются ли беззнаковые суффиксы для числовых литералов в любой побитовой операции (во избежание UB)? В частности, в отношении сдвигов я думаю, что это неопределенное поведение при использовании знаковых чисел, и я понимаю, что литералы подписаны, но я не уверен. Т.е.
4 << x; // or is 4U << x required?
4 >> x;
4 & x;
4 | x;
// etc. for all bit ops
x << 4;
x >> 4;
// etc.
где 4 — заполнитель для любого литерала.
Я знаю, что большинству компиляторов все равно, меня просто интересует, что говорит спецификация.
Нет, суффикс unsigned
не является строго обязательным при использовании побитовых операторов, поскольку стандарт ANSI C в главе 2.9 гласит, что побитовые операторы должны применяться к целочисленным операндам signed
или unsigned
(char
, short
, int
и long
).
Однако, особенно при сдвигах, где количество битов для сдвига не может быть отрицательным числом, было бы несколько правильнее указать его в любом случае.
Очевидно, вам также понадобится суффикс, когда литерал не вписывается в целое число.
@tofro почему? Если литерал не помещается в int
, автоматически будет выбран наибольший целочисленный тип. Вы имели в виду "если результат смещения" не подходит?
Ни одна версия стандарта C, от стандарта ANSI C 1990 года до стандарта ISO C 2023 года, не имеет главы 2.9, раздела 2.9 или пункта 2.9. Возможно, вы имеете в виду «Язык программирования C» Кернигана и Ритчи, в разделе 2.9 обоих изданий которого рассматриваются побитовые операторы. На обложке второго издания имеется красная печать «ANSI C», но это маркетинговый ход, указывающий на то, что книга была обновлена с учетом стандарта ANSI C. Это не означает, что книга соответствует стандарту ANSI C.
В стандарте C нет запрета на использование целочисленного литерала (который в стандарте называется «константой») без беззнакового суффикса. Однако для получения желаемого результата может потребоваться суффикс.
Проще всего рассмотреть 1 << n
, где n
— 31, а int
— 32 бита. Тогда 1 << n
не определяется стандартом C, поскольку 231 не представимо в int
, но 1u << n
определено.
Понимаю. Спасибо. Думаю, тогда я задал неправильный вопрос, на самом деле я хотел спросить «исключить случай, когда число непредставимо, для каких побитовых операций результат будет отличаться при использовании беззнакового и знакового литерала».
4 << x
вызовет UB для некоторых (не всех) значенийx
.4U << x
также вызовет UB для некоторых (не всех) значенийx
. В любом случае вы можете не предоставлять такие значения.