Подтвердить что ты не робот

Почему C/С++ ненавидят подпись char так много?

Почему C разрешает доступ к объекту с использованием "типа символа":

6.5 Выражения (C)

Объект должен иметь сохраненное значение, доступное только с помощью выражения lvalue, которое имеет один из следующих типов:

  • тип символа.

но С++ допускает char и без знака char?

3.10 Lvalues ​​и rvalues ​​ (С++)

Если программа пытается получить доступ к сохраненному значению объекта через значение gl другого, чем одно из следующих типов, поведение undefined:

  • a char или неподписанный char тип.

Еще одна часть подписанной char ненависти (цитата из стандарта С++):

3.9 Типы (С++)

Для любого объекта (кроме подобъекта базового класса) тривиально-скопируемого типа T, независимо от того, имеет ли объект правильное значение типа T, базовые байты, составляющие объект, могут быть скопированы в массив char или без знака char. Если содержимое массива char или без знака char будет скопировано обратно в объект, объект должен сохранить первоначальное значение.

И из стандарта C:

6.2.6 Представления типов (C)

Значения, хранящиеся в объектах без битового поля любого другого типа объекта, состоят из бит n × CHAR_BIT, где n - размер объекта этого типа, в байтах. Значение может быть скопировано в объект типа без знака char [n] (например, memcpy); результирующий набор байтов называется представлением объекта значения.

Я вижу много людей в stackoverflow, потому что unsigned char - единственный тип символа, который не имеет битов заполнения, но раздел C99 6.2.6.2. Целочисленные типы говорит

подписанный char, не должен иметь никаких добавочных битов

Итак, какова истинная причина этого?

4b9b3361

Ответ 1

Здесь я беру на себя мотивацию:

В системе без двоичного дополнения signed char не подходит для доступа к представлению объекта. Это связано с тем, что есть два возможных представления signed char, которые имеют одинаковое значение (+0 и -0) или одно представление, которое не имеет значения (представление ловушки). В любом случае это мешает вам делать наиболее значимые вещи, которые вы можете сделать с представлением объекта. Например, если у вас есть 16-разрядное целое число без знака 0x80ff, один или другой байт, как signed char, будет либо ловушкой, либо сравняться с 0.

Обратите внимание, что в такой реализации (не-двоичное дополнение) plain char необходимо определить как неподписанный тип для доступа к представлениям объектов через char для правильной работы. Хотя явного требования нет, я рассматриваю это как требование, вытекающее из других требований стандарта.

Ответ 2

Я думаю, что вы действительно задаетесь вопросом, почему signed char дисквалифицирован из всех правил, позволяющих вводить t-tning в качестве специального случая. Честно говоря, я не знаю, тем более, что — насколько я могу судить; signed char тоже не может быть дополнением:

[C++11: 3.9.1/1]: [..] A char, a signed char и a unsigned char занимают одинаковое количество хранения и имеют одинаковые требования к выравниванию (3.11); то есть они имеют одно и то же представление объекта. Для типов символов в представлении значения участвуют все биты представления объекта. [..]

Эмпирические данные свидетельствуют о том, что это не намного больше, чем соглашение:

  • char рассматривается как байт ASCII;
  • unsigned char рассматривается как байт с произвольным "двоичным" контентом; и
  • signed char остается ветром на ветру.

Для меня это не кажется достаточным основанием для исключения из этих стандартных правил, но я честно не могу найти никаких доказательств обратного. Я собираюсь привести его к мягко необъяснимой странности в стандартной формулировке.

(Возможно, нам нужно задать список std-discussion об этом.)

Ответ 3

Использование типа символа для проверки представлений объектов - это взломать. Тем не менее, это исторический, и для его размещения необходимо сделать какое-то жилье.

В основном, в языках программирования нам требуется сильная типизация. То, что есть float, должно быть доступно как float, а не как int. Это имеет ряд преимуществ, включая сокращение человеческих ошибок и возможность различных оптимизаций.

Однако есть моменты, когда необходимо получить доступ или изменить байты объекта. В C это было сделано через типы символов. С++ продолжает эту традицию, но это немного улучшает ситуацию, устраняя использование signed char для этих целей.

В идеале было бы лучше создать новый тип, скажем byte, и разрешить доступ к байтам только для представления объектов только через этот тип, тем самым отделяя обычные типы символов только для использования в качестве обычных целых чисел/символов. Возможно, считалось, что существует слишком много существующего кода, использующего char и unsigned char для поддержки такого изменения. Тем не менее, я никогда не видел, чтобы signed char использовался для доступа к представлению объекта, поэтому было бы безопасно его исключить.