В C/С++ для чего используется unsigned char
? Как он отличается от обычного char
?
В С++ существуют три различных типа символов:
char
signed char
unsigned char
Если вы используете типы символов для текста, используйте неквалифицированный char
:
'a'
или '0'
."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
.
Это зависит от реализации, так как стандарт 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
, если вы действительно хотите представлять маленькие целые числа.
Поскольку я чувствую, что это действительно вызвано, я просто хочу указать некоторые правила 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;
Также следует, что преобразование - это не просто усечение битов более высокого порядка. Счастливое событие для двух дополнений состоит в том, что это просто усечение там, но то же самое не обязательно верно для других знаковых представлений.
UCHAR_MAX
?
~0
.
Как, например, использование unsigned char:
unsigend char часто используется в компьютерной графике, которая очень часто (хотя и не всегда) назначает один байт каждому цветовому компоненту. Обычно наблюдается цвет RGB (или RGBA), представленный как 24 (или 32) бита, каждый без знака char. Поскольку значения без знака char попадают в диапазон [0,255], значения обычно интерпретируются как
Таким образом, вы получите 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 которое неверно.
Если вы хотите использовать символ как маленькое целое число, самый безопасный способ сделать это - это типы int8_t
и uint8_t
.
int8_t
и uint8_t
являются необязательными и не определены в архитектурах, где размер байта не равен 8 битам. И наоборот, signed char
и unsigned char
всегда доступны и гарантированно содержат не менее 8 бит. Это может быть общий путь, но не самый безопасный .
char
и unsigned char
не гарантируются как 8-разрядные типы на всех платформах, они гарантированно будут 8 бит или больше. На некоторых платформах 9-битный, 32-разрядный или 64-разрядный байты. Однако наиболее распространенные платформы сегодня (Windows, Mac, Linux x86 и т.д.) Имеют 8-разрядные байты.
unsigned char
принимает только положительные значения.... например 0 до 255
где as
signed char
принимает как положительные, так и отрицательные значения.... например -128 до +127
signed char
имеет диапазон от -128 до 127; unsigned char
имеет диапазон от 0 до 255.
char
будет эквивалентен либо подписанному char, либо unsigned char, в зависимости от компилятора, но является отдельным типом.
Если вы используете строки стиля C, просто используйте char
. Если вам нужно использовать символы для арифметики (довольно редко), укажите явно подписанный или неподписанный для переносимости.
В терминах прямых значений используется обычный 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 та же гарантия безопасного кастомизации типа не существует.
unsigned char
, а не массива , а любое «преобразование» определяется только формально путем копирования из объекта в реальный объявленный массив unsigned char
последующей проверкой последнего. Не ясно, может ли OR быть интерпретировано как такой массив напрямую, с учетом арифметики указателей, которое это повлечет за собой, т. Е. Будет ли "sequence" ==
"array" в этом использовании. Есть основная проблема № 1701, открытая в надежде получить разъяснения. К счастью, эта неоднозначность действительно беспокоит меня в последнее время.
Беззнаковое char представляет собой (без знака) байтовое значение (от 0 до 255). Возможно, вы думаете о "char" в терминах "персонажа", но это действительно числовое значение. Обычный "char" подписан, поэтому у вас есть 128 значений, и эти значения сопоставляются символам с использованием кодировки ASCII. Но в любом случае то, что вы храните в памяти, является байтовым значением.
unsigned char - это основа всей хитрости. Почти во всех компиляторах для всей платформы unsigned char является просто BYTE. Целое число без знака (обычно) 8 бит. который можно рассматривать как небольшое целое или пакет бит.
В зависимости от того, как сказал кто-то другой, стандарт не определяет знак char. поэтому у вас есть 3 разных типа "char": char, подписан char, unsigned char.
Если вам нравится использовать различные типы определенной длины и подписи, вам, вероятно, лучше работать с uint8_t, int8_t, uint16_t и т.д. просто потому, что они делают именно то, что они говорят.
unsigned char принимает только положительные значения: от 0 до 255 подписанный char принимает положительные и отрицательные значения: от -128 до +127
беззнаковые числа always positive or zero
и подчиняются laws of arithmetic modulo 2^n
, где n
- количество бит в типе.
пример: если символы имеют 8 бит, переменные unsigned char
имеют значения между 0 and 255
, а signed chars
имеют значения между -128 and 127.
Некоторые поисковики обнаружили это, где люди обсуждали это.
Беззнаковый char является в основном одиночным байтом. Таким образом, вы использовали бы это, если вам нужен один байт данных (например, возможно, вы хотите использовать его для установки и включения флажков для функции, как это часто делается в Windows API).
цитируется из книги "c программирования laugage":
К char или любому целому числу может применяться квалификатор signed
или unsigned
. беззнаковые числа
всегда положительны или равны нулю и подчиняются законам арифметики по модулю 2 ^ n, где n - число
бит в типе. Так, например, если символы имеют 8 бит, переменные без знака char имеют значения
между 0 и 255, в то время как подписанные символы имеют значения от -128 до 127 (в два раза
добавьте машину.) Являются ли простые символы подписанными или неподписанными являются зависящими от машины,
но печатные символы всегда положительны.
Беззнаковый char использует бит, который зарезервирован для знака обычного char как еще один номер. Это изменяет диапазон на [0 - 255] в отличие от [-128 - 127].
Обычно символы без знака используются, когда вам не нужен знак. Это будет иметь значение при выполнении таких вещей, как смещение битов (сдвиг расширяет знак) и другие вещи при работе с char как байт, а не использование его как числа.