Вопрос
В C/C++ что за unsigned char
используется для?Чем он отличается от обычного char
?
Решение
В 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
.
Другие советы
Это зависит от реализации, поскольку стандарт 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
если вы действительно хотите представлять небольшие целые числа.
Поскольку я чувствую, что это действительно необходимо, я просто хочу сформулировать некоторые правила C и C++ (в этом отношении они одинаковы).Первый, все биты из unsigned char
участвовать в определении значения любого беззнакового объекта char.Второй, unsigned char
явно указано без знака.
Я обсуждал с кем-то, что происходит, когда вы конвертируете значение -1
типа int в unsigned char
.Он отказался от идеи, что в результате unsigned char
все его биты установлены в 1, потому что он беспокоился о представлении знаков.Но ему это не обязательно.Из этого правила сразу следует, что преобразование делает то, что задумано:
Если новый тип не имеет значения, значение преобразуется путем повторного добавления или вычитания одного больше, чем максимальное значение, которое может быть представлено в новом типе, пока значение не будет в диапазоне нового типа.(
6.3.1.3p2
в проекте C99)
Это математическое описание.C++ описывает это в терминах исчисления по модулю, которое подчиняется тому же правилу.В любом случае, что такое нет гарантировано, что все биты целого числа -1
являются одним до преобразования.Итак, что мы имеем, чтобы можно было утверждать, что полученный результат unsigned char
имеет все свои CHAR_BIT
биты превратились в 1?
- В определении его значения участвуют все биты — то есть в объекте не возникает никаких битов заполнения.
- Добавление только один раз
UCHAR_MAX+1
к-1
даст значение в диапазоне, а именноUCHAR_MAX
На самом деле этого достаточно!Поэтому всякий раз, когда вы хотите иметь unsigned char
имея все свои биты в одном, вы делаете
unsigned char c = (unsigned char)-1;
Отсюда также следует, что преобразование нет просто усекая биты более высокого порядка.Счастливое событие для дополнение до двух в том, что здесь это просто усечение, но то же самое не обязательно верно для других представлений знаков.
Как, например, использование беззнаковый символ:
беззнаковый символ часто используется в компьютерной графике, где очень часто (хотя и не всегда) каждому цветовому компоненту присваивается один байт.Обычно цвет RGB (или RGBA) представлен в виде 24 (или 32) битов, каждый из которых представляет собой беззнаковый символ.С беззнаковый символ значения попадают в диапазон [0,255], значения обычно интерпретируются как:
- 0 означает полное отсутствие данного цветового компонента.
- 255 означает 100% данного цветового пигмента.
Таким образом, вы получите красный цвет RGB как (255,0,0) -> (100% красный, 0% зеленый, 0% синий).
Почему бы не использовать подписанный символ?Арифметика и сдвиг битов становятся проблематичными.Как уже объяснялось, подписанный символДиапазон существенно сдвинут на -128.Очень простой и наивный (в основном неиспользуемый) метод преобразования RGB в оттенки серого заключается в усреднении всех трех цветовых компонентов, но при этом возникают проблемы, когда значения цветовых компонентов отрицательны.Красный (255, 0, 0) в среднем равен (85, 85, 85) при использовании беззнаковый символ арифметика.Однако если бы значения были подписанный символs (127,-128,-128), мы получим (-99, -99, -99), что будет (29, 29, 29) в нашем беззнаковый символ пространство, что неверно.
Если вы хотите использовать символ как небольшое целое число, самый безопасный способ сделать это — использовать int8_t
и uint8_t
типы.
signed char
имеет диапазон от -128 до 127; unsigned char
имеет диапазон от 0 до 255.
char
будет эквивалентен либо подписанному char, либо unsigned char, в зависимости от компилятора, но является отдельным типом.
Если вы используете строки в стиле C, просто используйте char
.Если вам нужно использовать символы для арифметических операций (довольно редко), явно укажите знак или без знака для переносимости.
char
и unsigned char
не обязательно будут 8-битными типами на всех платформах — они гарантированно будут 8-битными или больше.Некоторые платформы имеют 9-битные, 32-битные или 64-битные байты.Однако наиболее распространенные сегодня платформы (Windows, Mac, Linux x86 и т. д.) имеют 8-битные байты.
Что касается прямых значений, обычный символ используется, когда известно, что значения находятся между CHAR_MIN
и CHAR_MAX
в то время как беззнаковый символ обеспечивает двойной диапазон на положительном конце.Например, если CHAR_BIT
8, диапазон штатный char
гарантированно будет только [0, 127] (потому что оно может быть знаковым или беззнаковым), в то время как unsigned char
будет [0, 255] и signed char
будет [-127, 127].
С точки зрения того, для чего он используется, стандарты позволяют объектам POD (простые старые данные) напрямую преобразовываться в массив беззнаковых символов.Это позволяет вам изучить представление и битовые комбинации объекта.Такой же гарантии безопасного каламбура не существует для char или подписанного char.
unsigned char
принимает только положительные значения....например 0 к 255
тогда как
signed char
принимает как положительные, так и отрицательные значения....например -128 к +127
Беззнаковый символ — это (беззнаковое) байтовое значение (от 0 до 255).Вы можете думать о «char» как о «символе», но на самом деле это числовое значение.Обычный «char» подписан, поэтому у вас есть 128 значений, и эти значения сопоставляются с символами с использованием кодировки ASCII.Но в любом случае то, что вы сохраняете в памяти, представляет собой байтовое значение.
Если вам нравится использовать различные типы определенной длины и знака, вам, вероятно, лучше использовать uint8_t, int8_t, uint16_t и т. д. просто потому, что они делают именно то, что говорят.
Беззнаковый символ использует бит, зарезервированный для знака обычного символа, в качестве другого числа.Это изменит диапазон на [0–255] вместо [-128–127].
Обычно беззнаковые символы используются, когда вам не нужен знак.Это будет иметь значение при выполнении таких действий, как сдвиг битов (сдвиг расширяет знак) и других вещах, когда вы работаете с символом как с байтом, а не с использованием его как числа.
unsigned char — это сердце всех битовых трюков.В почти ВСЕХ компиляторах для ВСЕХ платформ беззнаковый символ — это просто БАЙТ.Беззнаковое целое число (обычно) длиной 8 бит.которое можно рассматривать как небольшое целое число или пакет битов.
В зависимости, как сказал кто-то другой, стандарт не определяет признак символа.Итак, у вас есть 3 различных типа "char":char, знаковый символ, беззнаковый символ.
Кое-что погуглив нашел этот, где люди обсуждали это.
Беззнаковый символ по сути представляет собой один байт.Таким образом, вы можете использовать это, если вам нужен один байт данных (например, возможно, вы хотите использовать его для установки и выключения флагов для передачи функции, как это часто делается в Windows API).
цитата из книги «Язык программирования на языке Си»:
Отборочный турнир signed
или unsigned
может применяться к char или любому целому числу.Неподписанные цифры всегда являются положительными или нулевыми, и подчиняются законам арифметического модуля 2^n, где n - количество битов в типе.Так, например, если chars составляют 8 бит, не знаковые переменные HAR имеют значения от 0 до 255, в то время как подписанные ChARS имеют значения от -128 до 127 (в двухместной машине. -зависимые, но печатные символы всегда положительны.
unsigned char принимает только положительные значения:От 0 до 255 Подписано Чар требует положительных и отрицательных значений:от -128 до +127