Каков результат a & b?

Это неудобно, но побитовый оператор AND определен в стандарте С++ следующим образом (выделение мое).

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

Это выглядит для меня бессмысленным. Насколько я могу видеть, "побитовая функция И" не определена нигде в стандарте.

Я понимаю, что функция И хорошо понятна и, следовательно, может не потребовать объяснений. Значение слова "побитовое" также должно быть довольно ясным: эта функция применяется к соответствующим битам ее операндов. Однако то, что составляет биты операндов, не ясно.

Что дает?

Ответ 1

Это недоказано. Вопрос о том, что означает стандарт, когда он относится к побитовым операциям, является предметом нескольких отчетов о дефектах.

Например отчет о дефектах 1857: Дополнительные вопросы о битах:

Спецификация побитовых операций в 5.11 [expr.bit.and], 5.12 [expr.xor] и 5.13 [expr.or] использует термин undefined "поразрядный" при описании операций, не указывая, является ли это представление значения или объекта, которое находится в поле зрения.

Частью разрешения этого может быть определение "бит" (который иначе в настоящее время undefined в С++) в качестве значения заданной мощности 2.

и ответ был:

CWG решила переформулировать описание операций сами избегать ссылок на биты, отделяя больше вопросы определения "бит" и т.п. для выпуска 1943 года для дальнейшего рассмотрение.

и отчет о дефекте 1943 гласит:

CWG приняла решение на собрании 2014-06 (Rapperswil) для решения только ограниченное подмножество вопросов, поднятых по вопросам 1857 и 1861. Это вопрос является заполнителем для оставшихся вопросов, таких как определение "бит" в терминах значения 2 n указав, имеет ли бит-поле знаковый бит и т.д.

Мы можем видеть из этого отчета отчет о дефектах 1796: Является ли all-bits-zero для нулевых символов значимым требованием?, эта проблема что означает стандарт, когда он относится к битам, затронутым и затрагивающим другие разделы:

Согласно пункту 2.3 [lex.charset],

Основной набор символов выполнения и набор символов широкого исполнения должны содержать все элементы основного   исходный набор символов, плюс управляющие символы, представляющие предупреждение,   backspace и возврат каретки плюс нулевой символ (соответственно,   null широкий символ), представление которого имеет все нулевые биты.

Не ясно, что переносная программа может проверять биты представление; вместо этого он, по-видимому, будет ограничен изучением биты чисел, соответствующие представлению значения (3.9.1 [basic.fundamental] пункт 1). Это может быть более уместным потребовать, чтобы значение нулевого символа сравнивалось с 0 или '\ 0' вместо указания битовой диаграммы представления.

Существует аналогичная проблема для определения сдвига, побитового и, и побитовые или операторы: являются ли эти спецификации ограничениями на бит образ представления или значения, полученные в результате интерпретация этих моделей как чисел?

В этом случае разрешение должно было измениться:

имеет все нулевые биты

в

значение равно 0.

Обратите внимание, что как указано в ответе ecatmur, проект стандарта С++ откладывает до стандартного раздела C 5.2.4.2.1 в разделе 3.9.1 [basic.fundamental] в параграфе 3 он не относится к разделу 6.5/4 из стандарта C, который, по крайней мере, говорит нам, что результаты определены реализацией. Я объясняю в своем комментарии ниже, что стандарт С++ может включать только текст из нормативных ссылок явно.

Ответ 2

[basic.fundamental]/3 отсылает к C 5.2.4.2.1. Кажется разумным, что побитовые операторы в С++, будучи underspecified, должны аналогичным образом относиться к C, в этом случае 6.5.10/4:

Результатом двоичного и оператора является побитовое И из операндов (т.е. каждый бит в результат устанавливается тогда и только тогда, когда каждый из соответствующих битов в преобразованных операндах установлен).

Обратите внимание, что C 6.5/4 имеет:

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

Внутренние представления целых чисел, конечно, описаны в 6.2.6.2/1,/2.

Ответ 3

Стандарт С++ определяет хранилище как определенное количество бит. Реализация может решить, какой смысл приписывать конкретный бит; что, как сказано, двоичный И должен работать над концептуальными 0s и 1s, образующими конкретное представление типа.

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

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

Это означает, что для любого используемого физического представления двоичный И действует в соответствии с таблицей истинности для функции И (для каждого номера бит я беру биты A i и B i из соответствующих операндов и выдает значение 1, только если оба они равны 1, в противном случае производят 0 для бит R i). Результирующее значение остается интерпретировать реализацией, но все, что выбрано, он должен соответствовать другим ожиданиям в отношении других двоичных операций, таких как OR и XOR.

Ответ 4

С юридической точки зрения мы могли бы считать, что все побитовые операции имеют поведение undefined, поскольку они фактически не определены.

Более разумно, мы должны применять здравый смысл и ссылаться на общие значения этих операций, применяя их к битам операндов (отсюда и термин "поразрядный" ).

Но об этом ничего не говорится. Позор мой ответ не может считаться нормативной формулировкой.