Что такое неподписанный символ?

375

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

Теги:
char

17 ответов

479
Лучший ответ

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

  • char
  • signed char
  • unsigned char

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

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

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

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

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

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

  • 4
    Чтобы было ясно, могли бы вы иметь 32-разрядные символы и 32-разрядные целые числа и иметь sizeof (int)! = Sizeof (char)? Я знаю, что стандарт говорит sizeof (char) == 1, но является ли относительный размер (int) основанным на фактической разнице в размере или разнице в диапазоне?
  • 0
    Джозеф, sizeof дает размер представления объекта типа. если вы говорите 32-битное int, то первое мало о чем говорит. скорее всего, вы имеете в виду представление объекта (это физический размер - включая все биты заполнения).
Показать ещё 11 комментариев
74

Это зависит от реализации, так как стандарт 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) return 1. Вы можете получить число бит в char с помощью CHAR_BIT в limits.h. Хотя сегодня есть несколько платформ, где это будет нечто большее, чем 8.

В этом выпуске есть хорошее резюме этой проблемы .

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

  • 2
    подписанный символ имеет минимальный диапазон от -127 до 127, а не от -128 до 127
  • 3
    @ 12431234123412341234123: Технически верно, в том смысле, что стандарт С определяет минимальный диапазон от -127 до 127. Тем не менее, я призываю вас найти платформу, которая не использует арифметику двух дополнений. Почти на каждой современной платформе фактический диапазон подписанных символов будет от -128 до 127.
Показать ещё 1 комментарий
33

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

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

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

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

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

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

unsigned char c = (unsigned char)-1;

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

  • 2
    Почему бы просто не использовать UCHAR_MAX ?
  • 4
    Или короче ~0 .
Показать ещё 2 комментария
21

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

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

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

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

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

12

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

  • 2
    Не очень хорошая идея: int8_t и uint8_t являются необязательными и не определены в архитектурах, где размер байта не равен 8 битам. И наоборот, signed char и unsigned char всегда доступны и гарантированно содержат не менее 8 бит. Это может быть общий путь, но не самый безопасный .
  • 0
    Это комментарий, он не отвечает на вопрос.
5

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

3

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

где as

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

3

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

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

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

3

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

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

  • 0
    На самом деле, это чаще всего будет [-128, 128].
  • 0
    Стандарты только формально определяют представление объекта в виде последовательности unsigned char , а не массива , а любое «преобразование» определяется только формально путем копирования из объекта в реальный объявленный массив unsigned char последующей проверкой последнего. Не ясно, может ли OR быть интерпретировано как такой массив напрямую, с учетом арифметики указателей, которое это повлечет за собой, т. Е. Будет ли "sequence" == "array" в этом использовании. Есть основная проблема № 1701, открытая в надежде получить разъяснения. К счастью, эта неоднозначность действительно беспокоит меня в последнее время.
Показать ещё 3 комментария
3

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

2

unsigned char - это основа всей хитрости. Почти во всех компиляторах для всей платформы unsigned char является просто BYTE. Целое число без знака (обычно) 8 бит. который можно рассматривать как небольшое целое или пакет бит.

В зависимости от того, как сказал кто-то другой, стандарт не определяет знак char. поэтому у вас есть 3 разных типа "char": char, подписан char, unsigned char.

  • 1
    Немного хитрости, хитрости или взлома действительно вызывают привыкание ;-)
  • 3
    Это 0, которые вызывают проблемы. Чтобы избежать пагубной привычки, держитесь подальше от грубых кусочков.
2

Если вам нравится использовать различные типы определенной длины и подписи, вам, вероятно, лучше работать с uint8_t, int8_t, uint16_t и т.д. просто потому, что они делают именно то, что они говорят.

1

unsigned char принимает только положительные значения: от 0 до 255 подписанный char принимает положительные и отрицательные значения: от -128 до +127

1

беззнаковые числа always positive or zero и подчиняются laws of arithmetic modulo 2^n, где n - количество бит в типе.

пример: если символы имеют 8 бит, переменные unsigned char имеют значения между 0 and 255, а signed chars имеют значения между -128 and 127.

1

Некоторые поисковики обнаружили это, где люди обсуждали это.

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

0

цитируется из книги "c программирования laugage":

К char или любому целому числу может применяться квалификатор signed или unsigned. беззнаковые числа всегда положительны или равны нулю и подчиняются законам арифметики по модулю 2 ^ n, где n - число бит в типе. Так, например, если символы имеют 8 бит, переменные без знака char имеют значения между 0 и 255, в то время как подписанные символы имеют значения от -128 до 127 (в два раза добавьте машину.) Являются ли простые символы подписанными или неподписанными являются зависящими от машины, но печатные символы всегда положительны.

0

Беззнаковый char использует бит, который зарезервирован для знака обычного char как еще один номер. Это изменяет диапазон на [0 - 255] в отличие от [-128 - 127].

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню