Цитируемый ответ:
Я знаю, что здесь есть много правильных ответов, но я хотел бы добавить несколько цитат к смеси. Я приведу два стандарта: черновик C99 n1256 (в свободном доступе) и черновик C ++ n1905 (также в свободном доступе). В этих конкретных стандартах нет ничего особенного, они просто доступны бесплатно, и то, что оказалось проще всего найти в настоящий момент.
Версия C ++:
§5.3.2 ¶9: Согласно этому параграфу, значение ~(type)0
гарантированно установит все биты, если (type)
- тип без знака.
Операнд ~ должен иметь целочисленный тип или тип перечисления; результат - дополнение его операнда. Интегральные акции выполняются. Тип результата - это тип повышенного операнда.
§3.9.1 ¶4: это объясняет, как переполнение работает с числами без знака.
Целые числа без знака, объявленные как без знака, должны подчиняться законам арифметики по модулю 2 n , где n - количество бит в представлении значения этого конкретного размера целого числа.
§3.9.1 ¶7, плюс сноска 49: Это объясняет, что числа должны быть двоичными. Отсюда можно сделать вывод, что ~(type)0
должно быть наибольшим представимым числом в type
(поскольку в нем включены все биты и каждый бит аддитивен).
Представления целочисленных типов должны определять значения с использованием чистого
двоичная система счисления 49 .
49) Позиционное представление для целых чисел, использующее двоичные цифры 0 и 1, в котором значения, представленные последовательными битами, являются аддитивными, начинаются
с 1, и умножаются на последовательную интегральную степень 2, за исключением, возможно, бита с самой высокой позицией. (Адаптировано из American National
Словарь по системам обработки информации .)
Поскольку арифметика выполняется по модулю 2 n , гарантируется, что (type)-1
является наибольшим значением, представимым в этом типе. Также гарантируется, что ~(type)0
является наибольшим значением, представимым в этом типе. Поэтому они должны быть равны.
Версия C99:
В версии C99 это изложено гораздо более компактно и явно.
§6.5.3 ¶3:
Результатом оператора ~ является побитовое дополнение его (повышенного) операнда (то есть
каждый бит в результате устанавливается тогда и только тогда, когда соответствующий бит в преобразованном операнде равен
не установлен). Целочисленные продвижения выполняются на операнде, и результат имеет
повышенный тип. Если повышенный тип является беззнаковым типом, выражение ~ E эквивалентно
до максимального значения, представимого в этом типе минус E.
Как и в C ++, арифметика без знака гарантированно является модульной (я думаю, что я уже достаточно подробно изучил стандарты), поэтому стандарт C99 определенно гарантирует, что ~(type)0 == (type)-1
, и мы знаем из §6.5.3 №3 что в ~(type)0
должны быть установлены все биты.
Краткое содержание:
Да, это портативный. unsigned type x = -1;
гарантирует, что все биты установлены в соответствии со стандартом.
Сноска: Да, мы говорим о битах значения , а не битах заполнения . Однако я сомневаюсь, что вам нужно установить биты заполнения на один. Из недавнего вопроса переполнения стека ( link ) видно, что GCC был портирован на PDP-10, где тип long long
имеет один бит заполнения. В такой системе unsigned long long x = -1;
может не устанавливать этот бит заполнения равным 1. Однако вы сможете обнаружить это только при использовании приведения указателей, который в любом случае обычно не переносим.