Для чего используется unsigned char
в C / C ++? Чем он отличается от обычного char
?
Что такое беззнаковый символ?
Ответы (17)
В 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
.
signed char
составляет от -127 до 127, но, предполагая дополнение 2, вы получите от -128 до 127. И это довольно безопасное предположение.
- person Steve Jessop; 16.05.2012
sizeof
ставится пробел, потому что это не функция, а оператор. Имхо даже лучший стиль - опускать круглые скобки при выборе размера переменной. sizeof *p
или sizeof (int)
. Это позволяет быстро понять, применимо ли это к типу или переменной. Точно так же излишне ставить круглые скобки после return
. Это не функция.
- person Patrick Schlüter; 28.11.2014
char
: это тип символьных литералов, таких как 'a'
или '0'
. верно в C ++, но не в C. В C 'a'
является int
.
- person chux - Reinstate Monica; 10.05.2016
char
signed char
unsigned char
wchar_t
char8_t
char16_t
char_32_t
- person 김선달; 02.07.2021
Это зависит от реализации, так как стандарт 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
, если вы действительно хотите представлять небольшие целые числа.
CHAR_BIT
должен быть не менее 8 бит по стандарту.
- person martinkunev; 12.03.2019
Поскольку я чувствую, что это действительно необходимо, я просто хочу изложить некоторые правила C и C ++ (в этом отношении они одинаковы). Во-первых, все биты unsigned char
участвуют в определении значения любого объекта типа unsigned 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;
Из этого также следует, что преобразование - это не просто усечение битов более высокого порядка. Удачным событием для дополнения до двух является то, что это просто усечение, но то же самое не обязательно верно для других представлений знаков.
UCHAR_MAX
?
- person Nicolás; 05.01.2011
(unsigned type)-1
- это своего рода идиома. ~0
нет.
- person Patrick Schlüter; 28.11.2014
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
. Я действительно смущен, я думаю, что какое-то продвижение char в целочисленное что-то делает, но я не знаю.
- person Suraj Jain; 17.08.2016
Например, использование unsigned char:
unsigned char
часто используется в компьютерной графике, которая очень часто (хотя и не всегда) присваивает один байт каждому компоненту цвета. Обычно цвет RGB (или RGBA) представлен 24 (или 32) битами, каждый unsigned char
. Поскольку unsigned char
значения попадают в диапазон [0,255], значения обычно интерпретируются как:
- 0 означает полное отсутствие данного цветового компонента.
- 255 означает 100% данного цветового пигмента.
Таким образом, вы получите красный цвет RGB как (255,0,0) -> (100% красный, 0% зеленый, 0% синий).
Почему бы не использовать signed char
? Арифметика и сдвиг битов становятся проблематичными. Как уже объяснялось, диапазон signed char
существенно сдвинут на -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 бит. Это может быть распространенный способ, но не самый безопасный.
- person chqrlie; 07.04.2015
signed char
и unsigned char
? Или вы порекомендуете более безопасную альтернативу в этом конкретном случае? Например, по какой-то причине придерживаться реальных целочисленных типов signed int
и unsigned int
?
- person RobertS supports Monica Cellio; 21.12.2019
signed char
и unsigned char
переносимо для всех соответствующих реализаций и сэкономит место для хранения, но может вызвать некоторое увеличение размера кода. В некоторых случаях можно было бы сэкономить больше места для хранения, сохраняя небольшие значения в битовых полях или отдельных битах обычных целочисленных типов. На этот вопрос нет однозначного ответа, применимость этого подхода зависит от конкретного случая. И этот ответ в любом случае не отвечает на вопрос.
- person chqrlie; 21.12.2019
unsigned char
принимает только положительные значения ... например, от 0 до 255.
в то время как
signed char
принимает как положительные, так и отрицательные значения ... например, от -128 до +127
signed char
имеет диапазон от -128 до 127; unsigned char
имеет диапазон от 0 до 255.
char
будет эквивалентен символу со знаком или без знака, в зависимости от компилятора, но это отдельный тип.
Если вы используете строки в стиле C, просто используйте char
. Если вам нужно использовать символы для арифметики (довольно редко), укажите явно подписанный или неподписанный для переносимости.
char
и unsigned char
не гарантируют, что они будут 8-битными типами на всех платформах, они гарантированно будут 8-битными или больше. На некоторых платформах есть 9-битные, 32-битные или 64-битные байты.. Однако наиболее распространенные сегодня платформы (Windows, Mac, Linux x86 и т. Д.) Имеют 8-битные байты.
unsigned char
- это байтовое значение без знака (от 0 до 255). Вы можете думать о char
как о «персонаже», но на самом деле это числовое значение. Обычный char
подписан, поэтому у вас есть 128 значений, и эти значения сопоставляются с символами с использованием кодировки ASCII. Но в любом случае то, что вы храните в памяти, является байтовым значением.
char
не может быть байтом.
- person qwr; 08.07.2020
Что касается прямых значений, то обычный символ используется, когда известно, что значения находятся между CHAR_MIN
и CHAR_MAX
, в то время как беззнаковый символ обеспечивает двойной диапазон на положительном конце. Например, если CHAR_BIT
равно 8, диапазон обычного char
гарантированно будет только [0, 127] (потому что он может быть подписанным или беззнаковым), тогда как unsigned char
будет [0, 255], а signed char
будет [-127, 127] ].
С точки зрения того, для чего он используется, стандарты позволяют напрямую преобразовывать объекты POD (простые старые данные) в массив беззнаковых символов. Это позволяет вам исследовать представление и битовые шаблоны объекта. Такой же гарантии безопасного выбора типа не существует для char или signed char.
unsigned char
, а не как массив конкретно, и любое преобразование определяется только формально путем копирования из объект в реальный, объявленный массив из unsigned char
, а затем проверяет последний. Неясно, может ли OR быть напрямую переинтерпретировано как такой массив с учетом арифметики указателя, то есть, будет ли массив ==
в этом использовании. В надежде прояснить этот вопрос был открыт основной вопрос №1701. К счастью, эта двусмысленность в последнее время меня действительно беспокоит.
- person underscore_d; 30.08.2016
unsigned char
OR, а затем продолжить, используя ++ptr
оттуда, чтобы прочитать каждый его байт ... но AFAICT, это не конкретно определено как разрешенное, поэтому нам остается сделать вывод, что это "вероятно, нормально" из множества других отрывков (и во многих отношениях простого существования memcpy
) в Стандарте, сродни мозаике головоломка. Что не идеально. Что ж, может быть, формулировка со временем улучшится. Вот проблема CWG, о которой я упоминал, но не хватало места для ссылки - open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1701
- person underscore_d; 30.08.2016
unsigned char
- это суть всех хитростей. Почти во ВСЕХ компиляторах для ВСЕЙ платформы unsigned char
- это просто байт и целое число без знака (обычно) из 8 бит, которое можно рассматривать как небольшое целое число или как набор битов.
В зависимости, как сказал кто-то другой, стандарт не определяет знак символа. Итак, у вас есть 3 разных типа char
: char
, signed char
, unsigned char
.
Если вам нравится использовать различные типы определенной длины и подписи, вам, вероятно, лучше использовать uint8_t
, int8_t
, uint16_t
и т. Д. Просто потому, что они делают именно то, что говорят.
unsigned char
принимает только положительные значения: от 0 до 255, а signed char
принимает положительные и отрицательные значения: от -128 до +127.
Некоторые поисковые запросы нашли это, где люди обсуждали это.
Беззнаковый символ - это, по сути, один байт. Таким образом, вы могли бы использовать это, если вам нужен один байт данных (например, возможно, вы хотите использовать его для включения и выключения флагов, которые будут передаваться функции, как это часто делается в Windows API).
Беззнаковый символ использует бит, зарезервированный для знака обычного символа, в качестве другого числа. Это изменяет диапазон на [0 - 255], а не на [-128 - 127].
Обычно символы без знака используются, когда вам не нужен знак. Это будет иметь значение при выполнении таких вещей, как сдвиг бит (сдвиг расширяет знак) и других вещей при работе с char как байтом, а не с использованием его как числа.
цитируется из книги "Занятия по программированию на языке Си":
Квалификатор signed
или unsigned
может применяться к char или любому целому числу. Беззнаковые числа всегда положительны или равны нулю и подчиняются законам арифметики по модулю 2 ^ n, где n - количество бит в типе. Так, например, если символы равны 8 битам, переменные типа unsigned char имеют значения от 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
char
не гарантируется равным одному байту, а signed char
гарантированно удерживает только диапазон [-127,127] (хотя почти все системы используют дополнение до двух и содержат не менее [-128,127])
- person qwr; 08.07.2020