Что такое неподписанный символ?
В C/C++, что unsigned char
используется для? Чем он отличается от обычного char
?
16 ответов
В 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
, В зависимости от платформы, символ может быть 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 to 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;
Из этого также следует, что преобразование - это не просто усечение битов более высокого порядка. Удачным событием для дополнения двоих является то, что это просто усечение, но то же самое не обязательно верно для других представлений знаков.
Как например использование неподписанного символа:
unsigned char часто используется в компьютерной графике, которая очень часто (хотя и не всегда) назначает один байт для каждого компонента цвета. Обычно цвет RGB (или RGBA) представлен в виде 24 (или 32) битов, каждый из которых является беззнаковым символом. Поскольку значения unsigned char попадают в диапазон [0,255], значения обычно интерпретируются как:
- 0 означает полное отсутствие данного компонента цвета.
- 255 означает 100% данного цветного пигмента.
Таким образом, вы получите красный RGB как (255,0,0) -> (100% красный, 0% зеленый, 0% синий).
Почему бы не использовать подписанный символ? Арифметика и сдвиг бит становится проблематичным. Как уже объяснялось, диапазон подписанных символов существенно смещен на -128. Очень простой и наивный (в основном неиспользуемый) метод преобразования RGB в оттенки серого заключается в усреднении всех трех цветовых компонентов, но это приводит к проблемам, когда значения цветовых компонентов являются отрицательными. Красный (255, 0, 0) составляет в среднем (85, 85, 85) при использовании беззнаковой арифметики. Однако, если бы значения были подписаны char s (127, -128, -128), мы бы получили (-99, -99, -99), что будет (29, 29, 29) в нашем пространстве без знака., что неверно.
Если вы хотите использовать символ в качестве маленького целого числа, самый безопасный способ сделать это с помощью int8_t
а также uint8_t
типы.
signed char
имеет диапазон от -128 до 127; unsigned char
имеет диапазон от 0 до 255.
char
будет эквивалентен знаковому или неподписанному символу, в зависимости от компилятора, но это отдельный тип.
Если вы используете строки в стиле C, просто используйте char
, Если вам нужно использовать символы для арифметики (довольно редко), укажите подпись или без знака явно для переносимости.
unsigned char
принимает только положительные значения.... как от 0 до 255
в то время как
signed char
принимает как положительные, так и отрицательные значения.... как -128 до +127
Беззнаковый символ - это (беззнаковое) байтовое значение (от 0 до 255). Вы можете думать о "char" как о "персонаже", но на самом деле это числовое значение. Обычный символ "char" подписан, поэтому у вас есть 128 значений, и эти значения отображаются на символы с использованием кодировки ASCII. Но в любом случае то, что вы храните в памяти, является байтовым значением.
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 (простые старые данные) в массив без знака. Это позволяет вам исследовать представление и битовые структуры объекта. Та же самая гарантия безопасного типа наказания не существует для символа или подписанного символа.
Беззнаковый символ - сердце всех хитростей. Почти во всех компиляторах для платформы ALL неподписанный символ - это просто BYTE. Целое число без знака (обычно) 8 бит. это можно рассматривать как маленькое целое число или пакет битов.
В зависимости, как сказал кто-то еще, стандарт не определяет знак символа. Таким образом, у вас есть 3 различных типа "char": char, подписанный char, unsigned char.
Если вам нравится использовать различные типы определенной длины и подписи, вам, вероятно, лучше использовать uint8_t, int8_t, uint16_t и т. Д. Просто потому, что они делают именно то, что говорят.
char без знака принимает только положительные значения: от 0 до 255 char со знаком принимает положительные и отрицательные значения: от -128 до +127
Некоторые погуглили это, где люди обсуждали это.
Беззнаковый символ - это в основном один байт. Таким образом, вы могли бы использовать это, если вам нужен один байт данных (например, возможно, вы захотите использовать его для включения и выключения флагов, передаваемых в функцию, как это часто делается в Windows API).
Беззнаковый символ использует бит, который зарезервирован для знака обычного символа, в качестве другого числа. Это изменяет диапазон на [0 - 255], а не на [-128 - 127].
Обычно неподписанные символы используются, когда вы не хотите знак. Это будет иметь значение, когда выполняются такие вещи, как смещение битов (смещение расширяет знак) и другие вещи при работе с символом как байтом, а не с использованием его в качестве числа.
Процитирован из книги "C программирования laugage":
Классификатор signed
или же unsigned
может применяться к символу или любому целому числу. числа без знака всегда положительны или равны нулю и подчиняются законам арифметики по модулю 2^n, где n - количество бит в типе. Так, например, если символы состоят из 8 битов, переменные без знака имеют значения от 0 до 255, в то время как знаковые символы имеют значения от -128 до 127 (в машине дополнения до двух). Независимо от того, являются ли обычные символы со знаком или без знака, это машина -зависимые, но печатные символы всегда положительны.
signed char
а также unsigned char
оба представляют 1 байт, но имеют разные диапазоны.
Type | range
-------------------------------
signed char | -128 to +127
unsigned char | 0 to 255
В signed char
если мы рассмотрим char letter = 'A'
, 'A' представляет двоичное число 65 в ASCII/Unicode
, Если можно сохранить 65, можно также сохранить -65. Нет отрицательных двоичных значений вASCII/Unicode
нет необходимости беспокоиться об отрицательных значениях.
пример
#include <stdio.h>
int main()
{
signed char char1 = 255;
signed char char2 = -128;
unsigned char char3 = 255;
unsigned char char4 = -128;
printf("Signed char(255) : %d\n",char1);
printf("Unsigned char(255) : %d\n",char3);
printf("\nSigned char(-128) : %d\n",char2);
printf("Unsigned char(-128) : %d\n",char4);
return 0;
}
Выход -:
Signed char(255) : -1
Unsigned char(255) : 255
Signed char(-128) : -128
Unsigned char(-128) : 128
числа без знака always positive or zero
и подчиняться laws of arithmetic modulo 2^n
, где n
количество бит в типе
пример: если символы 8 битов, unsigned char
переменные имеют значения между 0 and 255
, в то время как signed chars
иметь значения между -128 and 127.