В C / C ++, для чего unsigned char
используется? Чем он отличается от обычного char
?
В C ++ есть три разных типа символов:
char
signed char
unsigned char
Если вы используете типы символов для текста , используйте неквалифицированное char
:
'a'
или '0'
."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
.
sizeof
потому что это не функция, а оператор. ИМХО, даже лучше, не использовать круглые скобки при определении размера переменной.sizeof *p
илиsizeof (int)
. Это быстро дает понять, относится ли это к типу или переменной. Кроме того, после него необходимо ставить круглые скобкиreturn
. Это не функция.char
: это тип символьных литералов, подобных'a'
или'0'
." верно в C ++, но не в C. В C'a'
естьint
.Это зависит от реализации, так как стандарт 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
inlimits.h
. Однако сегодня существует немного платформ, где это будет нечто иное, чем8
.Существует резюме хорошего этого вопроса здесь .
Как уже упоминалось с тех пор, как я это опубликовал, лучше использовать,
int8_t
иuint8_t
если вы действительно хотите представлять маленькие целые числа.источник
CHAR_BIT
Стандарт должен быть не менее 8 бит.Поскольку я чувствую, что это действительно необходимо, я просто хочу изложить некоторые правила C и C ++ (они одинаковы в этом отношении). Во- первых, все биты от
unsigned char
участия в определении стоимости , если какой - либо объект без знака полукокса. Во-вторых,unsigned char
явно указано без знака.Теперь у меня была дискуссия с кем-то о том, что происходит, когда вы конвертируете значение
-1
типа int вunsigned char
. Он отказался от идеи, что в результатеunsigned char
все биты установлены в 1, потому что он беспокоился о представлении знака. Но он не должен. Из этого правила сразу следует, что преобразование выполняет то, что предназначено:Это математическое описание. С ++ описывает это в терминах исчисления по модулю, которое подчиняется тому же правилу. В любом случае, не гарантируется, что все биты в целом числе
-1
равны единице перед преобразованием. Итак, что у нас есть, чтобы мы могли утверждать, что в результатеunsigned char
все егоCHAR_BIT
биты обращены в 1?UCHAR_MAX+1
чтобы-1
даст значение в диапазоне, а именноUCHAR_MAX
На самом деле этого достаточно! Поэтому, когда вы хотите иметь
unsigned char
все свои биты один, вы делаетеИз этого также следует, что преобразование - это не просто усечение битов более высокого порядка. Счастливым событием для дополнения двоих является то, что это просто усечение, но то же самое не обязательно верно для других представлений знака.
источник
UCHAR_MAX
?(unsigned type)-1
это какая-то идиома.~0
нет.int x = 1234
иchar *y = &x
. Двоичное представление1234
есть00000000 00000000 00000100 11010010
. Моя машина имеет прямой порядок байтов, поэтому она переворачивает ее и сохраняет в памяти11010010 00000100 00000000 00000000
LSB. Теперь основная часть. если я используюprintf("%d" , *p)
.printf
прочтете первые байты11010010
только выход ,-46
но11010010
это210
так , почему же распечатать-46
. Я действительно смущен, я думаю, что какой-то символ для целочисленного продвижения делает что-то, но я не знаю.Как например использование неподписанного символа :
unsigned char
часто используется в компьютерной графике, которая очень часто (хотя и не всегда) назначает один байт для каждого компонента цвета. Обычно цвет RGB (или RGBA) представлен в виде 24 (или 32) битов, каждый из которых представляет собойunsigned char
. Посколькуunsigned char
значения попадают в диапазон [0,255], значения обычно интерпретируются как:Таким образом, вы получите красный RGB как (255,0,0) -> (100% красный, 0% зеленый, 0% синий).
Почему бы не использовать
signed char
? Арифметика и сдвиг бит становится проблематичным. Как уже объяснялось,signed char
диапазон a существенно смещен на -128. Очень простой и наивный (в основном неиспользуемый) метод преобразования RGB в оттенки серого заключается в усреднении всех трех цветовых компонентов, но это приводит к проблемам, когда значения цветовых компонентов являются отрицательными. Красный (255, 0, 0) составляет в среднем (85, 85, 85) при использованииunsigned char
арифметики. Однако, если бы значения былиsigned char
s (127, -128, -128), мы бы получили (-99, -99, -99), что будет (29, 29, 29) в нашемunsigned char
пространстве, что неверно ,источник
Если вы хотите использовать символ в виде небольшого целого числа, самый безопасный способ сделать это с
int8_t
иuint8_t
типов.источник
int8_t
а неuint8_t
являются обязательными и не определены на архитектурах , где размер байт не ровно 8 бит. С другой стороны ,signed char
иunsigned char
всегда доступны и гарантированно трюма не менее 8 бит. Это может быть общий путь, но не самый безопасный .signed char
иunsigned char
? Или вы бы порекомендовали лучшую "более безопасную" альтернативу в этом конкретном случае? Например придерживаться «настоящих» целочисленных типовsigned int
иunsigned int
вместо этого по какой-то причине?signed char
иunsigned char
является переносимым для всех соответствующих реализаций и сэкономит место на диске, но может привести к некоторому увеличению размера кода. В некоторых случаях можно было бы сэкономить больше места для хранения, сохраняя небольшие значения в битовых полях или отдельные биты обычных целочисленных типов. Нет абсолютного ответа на этот вопрос, уместность этого подхода зависит от конкретного случая под рукой. И этот ответ никак не касается вопроса.unsigned char
принимает только положительные значения .... как от 0 до 255в то время как
signed char
принимает как положительные, так и отрицательные значения .... как -128 до +127источник
char
иunsigned char
не гарантируется, что они будут 8-битными типами на всех платформах - они гарантированно будут 8-битными или больше. Некоторые платформы имеют 9-битные, 32-битные или 64-битные байты . Однако наиболее распространенные на сегодняшний день платформы (Windows, Mac, Linux x86 и т. Д.) Имеют 8-битные байты.источник
signed char
имеет диапазон от -128 до 127;unsigned char
имеет диапазон от 0 до 255.char
будет эквивалентен знаковому или неподписанному символу, в зависимости от компилятора, но это отдельный тип.Если вы используете строки в стиле C, просто используйте
char
. Если вам нужно использовать символы для арифметики (довольно редко), укажите для подписи явно или без знака для переносимости.источник
An
unsigned char
является байтовым значением без знака (от 0 до 255). Вы можете думать о том,char
чтобы быть «персонажем», но это действительно числовое значение. Регулярное числоchar
подписано, поэтому у вас есть 128 значений, и эти значения отображаются на символы с использованием кодировки ASCII. Но в любом случае то, что вы храните в памяти, является байтовым значением.источник
С точки зрения прямых значений обычный символ используется , когда значения , как известно, между
CHAR_MIN
и вCHAR_MAX
то время как символ без знака обеспечивает двойную диапазон от положительного конца. Например, еслиCHAR_BIT
равно 8, диапазон регулярных значенийchar
гарантированно будет только [0, 127] (потому что он может быть подписан или без знака), аunsigned char
будет [0, 255] иsigned char
будет [-127, 127].С точки зрения того, для чего он используется, стандарты позволяют напрямую преобразовывать объекты POD (простые старые данные) в массив без знака. Это позволяет вам исследовать представление и битовые структуры объекта. Та же самая гарантия безопасного типа наказания не существует для символа или подписанного символа.
источник
unsigned char
, а не массива конкретно, и любое «преобразование» только формально определяются копирование от объекта к реальному, объявленному массиву изunsigned char
& затем проверок последних. Не ясно, может ли OR быть интерпретировано как такой массив напрямую, с учетом арифметики указателей, которое это повлечет за собой, т. Е. Будет ли «последовательность»==
«массивом» в этом использовании. Есть основная проблема № 1701, открытая в надежде получить разъяснения. К счастью, эта неоднозначность действительно беспокоит меня в последнее время.unsigned char
из ИЛИ, а затем продолжить использовать++ptr
оттуда для чтения каждого его байта ... но AFAICT, он не определен как разрешенный, поэтому мы Осталось сделать вывод, что «вероятно, все в порядке» из множества других отрывков (и во многих отношениях, просто существованияmemcpy
) в Стандарте, сродни мозаике. Что не идеально. Ну, возможно, формулировка улучшится в конце концов. Вот проблема CWG, о которой я упоминал, но не хватало места для ссылки - open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1701unsigned char
это сердце всей хитрости. Почти во всех компиляторах для платформы ALL этоunsigned char
просто байт и целое число без знака (обычно) 8 битов, которое можно рассматривать как маленькое целое число или пакет битов.В зависимости, как сказал кто-то еще, стандарт не определяет знак символа. поэтому у вас есть 3 различных
char
типов:char
,signed char
,unsigned char
.источник
Если вам нравится , используя различные типы длины конкретного и знаковости, вы , вероятно , лучше с
uint8_t
,int8_t
,uint16_t
и т.д. , просто потому , что они делают именно то , что они говорят.источник
Некоторые погуглили это , где люди обсуждали это.
Неподписанный символ - это в основном один байт. Таким образом, вы могли бы использовать это, если вам нужен один байт данных (например, может быть, вы хотите использовать его для включения и выключения флагов, передаваемых в функцию, как это часто делается в Windows API).
источник
Беззнаковый символ использует бит, зарезервированный для знака обычного символа, в качестве другого числа. Это изменяет диапазон на [0 - 255], а не на [-128 - 127].
Обычно неподписанные символы используются, когда вы не хотите знак. Это будет иметь значение при выполнении таких вещей, как смещение битов (смещение расширяет знак) и другие вещи при работе с символом как байтом, а не с использованием его в качестве числа.
источник
unsigned char
принимает только положительные значения: от 0 до 255, аsigned char
принимает положительные и отрицательные значения: от -128 до +127.источник
цитата из книги "C программирования laugage":
Квалификатор
signed
orunsigned
может применяться к char или любому целому числу. числа без знака всегда положительны или равны нулю и подчиняются законам арифметики по модулю 2 ^ n, где n - количество бит в типе. Так, например, если символы состоят из 8 битов, переменные без знака имеют значения от 0 до 255, в то время как знаковые символы имеют значения от -128 до 127 (в машине дополнения до двух). Независимо от того, являются ли обычные символы со знаком или без знака, это машина -зависимые, но печатные символы всегда положительны.источник
signed char
иunsigned char
оба представляют 1 байт, но у них разные диапазоны.В
signed char
случае, если мы рассмотримchar letter = 'A'
, «A» представляет двоичный код 65 вASCII/Unicode
, если 65 может быть сохранен, -65 также может быть сохранен. Там нет отрицательных двоичных значений,ASCII/Unicode
поэтому не нужно беспокоиться об отрицательных значениях.пример
Вывод -:
источник