Устанавливать все байты int (без знака char) 0, гарантированно представлять ноль?
Это не относится к рекомендуемой практике (а не к undefined), но о том, что на самом деле гарантирует стандарт С++, в вопросе превращения всех байтов целочисленного типа в значение (unsigned char)0
.суб >
Вопрос (ы)
В приведенном ниже фрагменте выражение, используемое оператором if, гарантируется, что оно будет оценено как true в С++ 11?
std::memset (
reinterpret_cast<char*> (&a), // int a;
(unsigned char)0,
sizeof (int)
);
if (a == 0) {
...
}
Прочитав цитаты из C99 и С++ 11 (далее в этом сообщении), мы обнаруживаем, что C99 явно гарантирует, что целочисленный тип со всеми битами, установленными в 0
, будет представлять значение 0
в этом типе.
Я не могу найти эту гарантию в стандарте С++ 11.
- Нет ли такой гарантии?
- Является ли результат предыдущего фрагмента действительно специфичным для реализации?
В C99 (ISO/IEC 9899: 1999)
5.2.1.2/1 Многобайтовые символы
Байт со всеми битами нуль должен интерпретироваться как нулевой символ независимо от состояния сдвига. Такой байт не должен быть частью какой-либо другой многобайтовый символ.
6.2.6.2/1 Целочисленные типы
Значения любых битов дополнений не определены. 45) Действительный (нелокальное) представление объекта со знаком целочисленного типа, где значный бит равен нулю - это действительное представление объекта соответствующего без знака, и будет представлять одно и то же значение.
Для любого целого тип, представление объекта, где все биты равны нулю, представление значения 0 в этом типе.
В С++ 11 (ISO/IEC 14882: 2011)
2.3/3 Наборы символов [lex.charset]
Основной набор символов выполнения и базовое выполнение широкоформатный набор должен содержать все элементы основного исходный набор символов, плюс управляющие символы, представляющие предупреждение, backspace и возврат каретки, плюс нулевой символ (соответственно, null широкий символ), представление которого имеет все нулевые биты.
Ответы
Ответ 1
С++ 11
Я думаю, что соответствующая часть
3.9.1/1 В С++ 11
Для типов символов участвуют все биты представления объекта в представлении стоимости. Для неподписанных типов символов все возможные битовые шаблоны представления значений представляют числа. Эти требования не подходят для других типов.
Наряду с 3.9.1/7
Представления интегральных типов определяет значения с помощью чистой двоичной системы нумерации.
C11
6.2.6.2 очень явный
Для беззнаковых целочисленных типов, отличных от unsigned char, биты объекта представление делится на две группы: биты значений и биты заполнения (необходимо не быть последним). Если бит N значений бит, каждый бит должен представлять собой мощность 2 между 1 и 2 N-1 так что объекты такого типа должны быть способны представляющие значения от 0 до 2 N - 1 с использованием чистого двоичного представления; это должно быть известный как представление значения. Значения любых битов дополнений не определены.
Для знаковых целых типов биты представления объекта должны быть разделены на три группы: биты значений, биты заполнения и знаковый бит. Не должно быть никаких битов заполнения; подписанный char не должен иметь никаких битов заполнения. Должен быть ровно один знаковый бит. Каждый бит, который является битом значения, должен иметь то же значение, что и один бит в объекте представление соответствующего неподписанного типа (если в подписанных тип и N в неподписанном типе, тогда M ≤ N). Если знаковый бит равен нулю, он не должен влиять на результирующее значение. Если знаковый бит равен единице, значение должно быть изменено в одном из следующими способами:
- соответствующее значение со знаком бит 0 отрицается (знак и величина);
- знаковый бит имеет значение - (2 M) (два дополнения);
- знаковый бит имеет значение - (2 M - 1) (одно дополнение).
Какое из них применяется, определяется реализацией, равно как и значение со знаком бит 1 и все биты значений ноль (для первых двух) или со знакомным битом и всеми битами значения 1 (для одного дополнения) являются представлением ловушки или нормальным значением. В случае знаков и величина и дополнение дополняют, если это представление является нормальным значением, оно называется отрицательный ноль.
Summmary
Я думаю, что намерение одинаково для обоих стандартных.
-
char
, signed char
и unsigned char
имеют все биты, участвующие в значении
-
другие целочисленные типы могут иметь биты заполнения, которые не участвуют в значении. Неправильный битовый шаблон в них может означать недопустимое значение.
-
интерпретация представляет собой чисто двоичное представление, то, чье определение расшифровывается в цитированной выше цитате C11.
Две вещи, которые могут быть непонятными:
-
can -0 (для знака и величины и дополнения _ones) - значение ловушки в С++
-
может один из битов заполнения быть битом четности (то есть мы можем изменить представление, если мы гарантируем, что биты заполнения не изменяются или нет).
Я был бы консервативным и давал бы да для обоих.
Ответ 2
Да, это гарантировано.
Поворот всех байтов/бит целочисленного типа гарантированно приведет к тому, что экземпляр типа имеет значение 0 (0
), как сказано в нижеприведенном фрагменте (-ах) из упомянутого стандарта.
3.9.1/7 Основные типы
Синоним интегрального типа - целочисленный. Представления интегральные типы должны определять значения с помощью чистой двоичной нумерации система. 49
49 позиционное представление для целых чисел, которое использует двоичные цифры 0 и 1, в которых значения, представленные последовательными битами, являются аддитивными, начинаются с 1 и умножаются на последовательную интегральную мощность 2, за исключением, возможно, бит с наивысшей позицией. (Адаптировано из Американского национального словаря для систем обработки информации.)
Ответ 3
Неа. Например, в стандарте нет ничего запрещающего представления, основанного на предвзятости, оно только требует, чтобы оно было двоичным.
Ответ 4
Нет. Я не верю, что это действительно гарантировано, но это довольно расплывчато.
Я был бы очень удивлен, если бы была когда-либо реализация на С++, в которой all-bits-zero не является представлением 0
, но я считаю, что такая реализация может быть совместимой (хотя и извращенной).
Давайте начнем с рассмотрения стандарта C99. (Да, я знаю, речь идет о С++, несите меня.) В нем говорится, что биты представления объекта беззнакового целочисленного типа делятся на две группы: биты значений и биты заполнения (там не должно быть никакого дополнения бит, и большинство реализаций их не имеют). Биты значений составляют чисто двоичное представление; биты заполнения не влияют на значение. Некоторые комбинации битов дополнений могут генерировать представление ловушки.
Подписанные типы схожи, с добавлением одного знакового бита. Подписанные типы могут быть представлены с использованием знака и величины, или двух дополнений, или одного дополнения - но опять же, любые биты заполнения не вносят вклад в значение, а некоторые комбинации битов заполнения могут генерировать ловушки.
Это описание не исключает возможности того, что, например, целочисленный тип, более широкий, чем char
, может иметь один бит заполнения, который всегда должен быть 1; если он равен 0, у вас есть ловушка. Или, возможно, более правдоподобно, он может иметь нечетный бит четности.
После публикации стандарта C99 второе Техническое исправление добавило следующее предложение, которое также появляется на C11.
Для любого целочисленного типа представление объекта, где все биты ноль должен быть представлением нулевого значения в этом типе.
Я хотел бы подчеркнуть, что это было добавлено как нормативный текст, а не как сноска, которая предлагает (но не доказывает), что члены комитета сочли, что гарантия уже не подразумевается в стандарте C99.
(C90 был гораздо менее специфичен в отношении того, как представляются целые типы.Они не упоминают биты заполнения, представления ловушек или двух'-дополнений и т.д. Я бы сказал, что он обеспечивал реализацию, по крайней мере, такую же гибкость, как и C99.)
Итак, начиная с C99 TC2, язык C гарантирует, что all-bits-zero является представлением нуля для любого целочисленного типа. В C99 и C90 эта гарантия не указана.
Что C. Что относительно С++?
В 2011 году стандарт С++, по-видимому, лишь немного более специфичен для представлений целочисленного типа как старый стандарт 1990 C. Для этого требуется, чтобы подписанные типы представлялись с использованием двух дополнений, 1 дополнения или знаковой величины. Он также требует "чистой двоичной системы нумерации". Он не упоминает "ловушечные представления" и не обсуждает биты дополнений, кроме как в контексте битовых полей.
Таким образом, как в C90, так и в pre-TC2 C99 теоретически возможно, чтобы все-бит-ноль представлял собой ловушечное представление для целочисленного типа. Стандартные требования С++ для целочисленных типов очень похожи на требования C90 и C99. Для этого требуется "чистое двоичное представление", но я бы сказал, что это применимо, как и в C99, только к битам ценности; хотя С++ не упоминает бит дополнений, он не запрещает их.
Опять же, это в основном теоретический интерес (таким образом, тег "язык-юрист" ). Комитету С было свободно навязывать требование о том, чтобы все бит-ноль представлял собой ноль, потому что все реализации уже удовлетворяли его. То же самое почти наверняка относится к С++.