Являются ли битовые флаги с использованием ints в C/С++ действительно безопасными?

Я заметил, что многие программисты на C/С++ реализуют наборы флагов, используя что-то вроде следующего:

#define FLAG_1 (1 << 0)
#define FLAG_2 (1 << 1)
#define FLAG_3 (1 << 2)

unsigned int my_flags = 0; /* no flag set */
my_flags |= FLAG_2; /* set flag 2 */

Но действительно ли этот подход звучит? Мне кажется, что он делает предположения о двоичном представлении unsigned ints, который не является частью стандарта языка C/С++. Например, что "0" на самом деле 0x0000.

Неужели я ошибаюсь? Или я прав в теории, но не на практике в настоящее время стандартное оборудование?

Ответы

Ответ 1

С++

Важной частью стандарта С++ 11 является §3.9.1/7 (ISO/IEC 14882: 2011 (E)):

Представления интегральных типов должны определять значения с использованием чистой двоичной системы нумерации.

Это поясняется в сноске:

49) Позиционное представление для целых чисел, которое использует двоичные цифры 0 и 1, в которых значения, представленные последовательными битами, являются аддитивными, начинаются с 1 и умножаются на последовательную интегральную мощность 2, за исключением, возможно, для бит с самое высокое положение. (Адаптировано из Американского национального словаря для систем обработки информации.)

Результаты операторов сдвига определяются математически. Например, для E1 << E2:

Если E1 имеет неподписанный тип, значение результата E1 × 2 E2 приведенное по модулю больше, чем максимальное значение, представляемое в типе результата. В противном случае, если E1 имеет подписанный тип и неотрицательное значение, а E1 × 2 E2 представляется в типе результата, то это результирующее значение; в противном случае поведение undefined.

Поразрядные операторы определяются как побитовые. Например, для побитового OR:

Выполняются обычные арифметические преобразования; результатом является побитовая исключительная функция OR операндов.

Конечно, в соответствии с правилом as-if представление действительно не должно быть чистой двоичной системой нумерации. Компилятор должен создавать только программу, которая действует так, как если бы она была.

С

В C99 (ISO/IEC 9899: TC3) чисто двоичная нотация гарантируется только для бит-полей и объектов типа unsigned char (§6.2.6.1/3):

Значения, хранящиеся в неподписанных битовых полях и объектах типа unsigned char, должны быть представлены с использованием чистой двоичной нотации.

Снова поясняется в сноске:

Позиционное представление для целых чисел, которое использует двоичные цифры 0 и 1, в которых значения, представленные последовательными битами, являются аддитивными, начинаются с 1 и умножаются на последовательные целые степени 2, за исключением, возможно, бит с наивысшим положением, (Адаптировано из Американского национального словаря для систем обработки информации.)

В стандарте конкретно указывается, что побитовые операции зависят от внутреннего представления (§6.5/4):

Некоторые операторы (унарный оператор ~ и бинарные операторы <, → , &, ^ и |, совместно описываемые как побитовые операторы), должны иметь операнды, которые имеют целочисленный тип. Эти операторы дают значения, зависящие от внутренних представлений целые числа и имеют определенные для реализации и undefined аспекты для подписанных типов.

Ответ 2

Хотя теоретически возможно запускать C или С++ в архитектуре, которая использует арифметику без полномочий 2, операторы |, & и ^ определены как имеющие поразрядное поведение, поэтому такой машине нужно будет эмулировать двоичную арифметику.

Таким образом, он полностью безопасен и портативен.

Ответ 3

Текущие стандарты C и С++ ограничивают представление без знака целочисленным представлением в чисто двоичное представление, поэтому то, что вы имеете выше, полностью безопасно и гарантированно работает.

Ответ 4

Перемещение битов вправо всегда уменьшает значение целого числа, тогда как смещение бит влево всегда увеличивает значение. Это независимо от того, является ли машина окончательной, поэтому, чтобы ответить на ваш вопрос: "Да, это звук, потому что смещение бит работает одинаково независимо от того, является ли система понятным"

Отвечает ли это на ваш вопрос?