Что такое неподписанный символ? - PullRequest
429 голосов
/ 16 сентября 2008

В C / C ++ для чего используется unsigned char? Чем он отличается от обычного char?

Ответы [ 16 ]

511 голосов
/ 18 сентября 2008

В C ++ существует три различных типа символов:

  • char
  • signed char
  • unsigned char

Если вы используете типы символов для текста , используйте неквалифицированное char:

  • это тип символьных литералов, таких как 'a' или '0'.
  • это тип, который составляет строки C, такие как "abcde"

Он также работает как числовое значение, но не указано, рассматривается ли это значение как подписанное или без знака. Остерегайтесь сравнений персонажей из-за неравенства - хотя если вы ограничиваете себя ASCII (0-127), вы почти в безопасности.

Если вы используете типы символов в качестве чисел , используйте:

  • signed char, что дает как минимум диапазон от -127 до 127. (Обычно от -128 до 127)
  • unsigned char, что дает как минимум диапазон от 0 до 255.

«По крайней мере», потому что стандарт C ++ дает только минимальный диапазон значений, который требуется охватить каждому числовому типу. sizeof (char) должно быть 1 (т. Е. Один байт), но теоретически байт может составлять, например, 32 бита. sizeof будет по-прежнему сообщать о его размере как 1 - это означает, что вы могли бы иметь sizeof (char) == sizeof (long) == 1.

79 голосов
/ 16 сентября 2008

Это зависит от реализации, так как стандарт C НЕ определяет подпись char. В зависимости от платформы, char может быть signed или unsigned, поэтому вам нужно явно запросить signed char или unsigned char, если ваша реализация зависит от него. Просто используйте char, если вы собираетесь представлять символы из строк, так как это будет соответствовать тому, что ваша платформа помещает в строку.

Разница между signed char и unsigned char такая, как вы и ожидали. На большинстве платформ signed char будет 8-разрядным двоичным дополнительным числом в диапазоне от -128 до 127, а unsigned char будет 8-разрядным целым числом без знака (0 до 255). Обратите внимание, что стандарт НЕ требует, чтобы типы char имели 8 битов, только то, что sizeof(char) возвращает 1. Вы можете получить количество бит в символе с CHAR_BIT в limits.h. Сегодня мало платформ, если это будет что-то отличное от 8.

Вот краткое изложение этой проблемы здесь .

Как уже упоминалось с тех пор, как я это опубликовал, лучше использовать int8_t и uint8_t, если вы действительно хотите представлять маленькие целые числа.

35 голосов
/ 14 января 2009

Поскольку я чувствую, что это действительно необходимо, я просто хочу изложить некоторые правила C и C ++ (они одинаковы в этом отношении). Во-первых, все биты из unsigned char участвуют в определении значения любого неподписанного объекта типа char. Во-вторых, unsigned char явно указано без знака.

Теперь я поговорил с кем-то о том, что происходит, когда вы конвертируете значение -1 типа int в unsigned char. Он отказался от идеи, что в результате unsigned char все биты установлены в 1, потому что он беспокоился о представлении знака. Но он не должен. Из этого правила сразу следует, что преобразование выполняет то, что предназначено:

Если новый тип без знака, значение преобразуется путем многократного добавления или вычитание больше, чем максимальное значение, которое может быть представлено в новом типе пока значение не окажется в диапазоне нового типа. (6.3.1.3p2 в черновике C99)

Это математическое описание. С ++ описывает это в терминах исчисления по модулю, которое подчиняется тому же правилу. В любом случае, не гарантирует, что все биты в целом числе -1 равны единице перед преобразованием. Итак, что же у нас есть, чтобы мы могли утверждать, что в результате unsigned char все его CHAR_BIT биты установлены в 1?

  1. Все биты участвуют в определении его значения, то есть в объекте не возникает битов заполнения.
  2. Добавление только одного раза UCHAR_MAX+1 к -1 приведет к значению в диапазоне, а именно: UCHAR_MAX

Этого достаточно, на самом деле! Поэтому, когда вы хотите, чтобы unsigned char имел все биты один, вы делаете

unsigned char c = (unsigned char)-1;

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

24 голосов
/ 17 сентября 2008

Как, например, использование unsigned char :

unsigned char часто используется в компьютерной графике, которая очень часто (хотя и не всегда) назначает отдельный байт для каждого компонента цвета. Обычно цвет RGB (или RGBA) представлен в виде 24 (или 32) битов, каждый из которых представляет собой беззнаковый символ . Поскольку значения unsigned char попадают в диапазон [0,255], значения обычно интерпретируются как:

  • 0 означает полное отсутствие данного компонента цвета.
  • 255 означает 100% данного цветного пигмента.

Таким образом, вы получите красный RGB как (255,0,0) -> (100% красный, 0% зеленый, 0% синий).

Почему бы не использовать знаковый символ ? Арифметика и сдвиг бит становится проблематичным. Как уже объяснено, диапазон со знаком char существенно смещен на -128. Очень простой и наивный (в основном неиспользуемый) метод преобразования RGB в оттенки серого заключается в усреднении всех трех цветовых компонентов, но это приводит к проблемам, когда значения цветовых компонентов являются отрицательными. Красный (255, 0, 0) составляет в среднем (85, 85, 85) при использовании арифметики без знака . Однако, если бы значения были знаковый символ с (127, -128, -128), мы бы получили (-99, -99, -99), что будет (29, 29, 29 ) в нашем поле без знака , что неверно.

12 голосов
/ 16 сентября 2008

Если вы хотите использовать символ в качестве маленького целого числа, самый безопасный способ сделать это с типами int8_t и uint8_t.

5 голосов
/ 17 сентября 2008

char и unsigned char не гарантированно будут 8-битными типами на всех платформах - они гарантированно будут 8-битными или более. Некоторые платформы имеют 9-битные, 32-битные или 64-битные байты . Однако наиболее распространенные на сегодняшний день платформы (Windows, Mac, Linux x86 и т. Д.) Имеют 8-битные байты.

5 голосов
/ 16 сентября 2008

signed char имеет диапазон от -128 до 127; unsigned char имеет диапазон от 0 до 255.

char будет эквивалентен знаковому или неподписанному символу, в зависимости от компилятора, но это отдельный тип.

Если вы используете строки в стиле C, просто используйте char. Если вам нужно использовать символы для арифметики (довольно редко), явно укажите подпись или без знака для переносимости.

4 голосов
/ 22 января 2013

unsigned char принимает только положительные значения .... как 0 до 255

где как

signed char принимает как положительные, так и отрицательные значения .... как -128 до + 127

4 голосов
/ 16 сентября 2008

В терминах прямых значений используется обычный символ, когда известно, что значения находятся в диапазоне от CHAR_MIN до CHAR_MAX, в то время как символ без знака обеспечивает двойной диапазон на положительном конце. Например, если CHAR_BIT равно 8, диапазон обычных char гарантированно будет только [0, 127] (потому что он может быть подписан или не подписан), тогда как unsigned char будет [0, 255] и * 1006. * будет [-127, 127].

С точки зрения того, для чего он используется, стандарты позволяют напрямую преобразовывать объекты POD (простые старые данные) в массив беззнаковых символов. Это позволяет вам изучить представление и битовые структуры объекта. Та же самая гарантия безопасного типа наказания не существует для символа или подписанного символа.

3 голосов
/ 16 сентября 2008

Беззнаковый символ - это (беззнаковое) байтовое значение (от 0 до 255). Вы можете думать о «char» как о «персонаже», но это действительно числовое значение. Обычный символ "char" подписан, поэтому у вас есть 128 значений, и эти значения отображаются на символы с использованием кодировки ASCII. Но в любом случае то, что вы храните в памяти, является байтовым значением.

...