Для чого C / C ++ для чого unsigned char
використовується? Чим він відрізняється від звичайного char
?
Для чого 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'
це an 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
в limits.h
. Сьогодні мало таких платформ, де це буде щось інше, ніж 8
, однак.
Існує резюме хорошого цього питання тут .
Як вже згадували інші, відколи я опублікував це, вам краще використовувати, int8_t
і uint8_t
якщо ви дійсно хочете представляти малі цілі числа.
CHAR_BIT
стандарт повинен бути не менше 8 біт.
Оскільки я відчуваю, що це дійсно вимагається, я просто хочу викласти деякі правила C і C ++ (у цьому плані вони однакові). По- перше, все біти від 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
?
(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% синій).
Чому б не використовувати a signed char
? Арифметика та зміщення бітів стає проблематичним. Як уже було пояснено, signed char
діапазон 's суттєво зміщується на -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
переноситься для всіх відповідних реалізацій і заощадить місце для зберігання, але може призвести до збільшення розміру коду. У деяких випадках можна заощадити більше місця для зберігання, зберігаючи невеликі значення в бітових полях або одиночних бітах регулярних цілих типів. На це питання немає абсолютної відповіді, доречність такого підходу залежить від конкретного випадку. І ця відповідь ніяк не стосується питання.
char
і unsigned char
не гарантується, що вони будуть 8-бітовими типами на всіх платформах - вони гарантовано будуть 8-бітовими або більшими. Деякі платформи мають 9-бітні, 32-бітні або 64-бітні байти . Однак найпоширеніші сьогодні платформи (Windows, Mac, Linux x86 тощо) мають 8-бітні байти.
signed char
має діапазон від -128 до 127; unsigned char
має діапазон від 0 до 255.
char
буде еквівалентним або підписаним char, або неподписаним char, залежно від компілятора, але є виразним типом.
Якщо ви використовуєте рядки в стилі C, просто використовуйте char
. Якщо вам потрібно використовувати символи для арифметики (досить рідко), вкажіть підписані або непідписані явно для переносу.
Ан 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 (звичайні старі дані) безпосередньо перетворюватися на масив неподписаних знаків. Це дозволяє вивчити представлення та бітові шаблони об’єкта. Таких же гарантій безпечного виду покарання не існує для char або підписаних char.
unsigned char
, а НЕ масиву конкретно, і будь-який «перетворення» тільки формально визначаються копіювання від об'єкта до реального, оголошеному масиву з unsigned char
& потім перевірок останніх. Незрозуміло, чи АБО можна безпосередньо переосмислити як такий масив, з припущеннями для арифметики вказівника це спричинило б, тобто чи "послідовність" ==
"масиву" в цьому використанні. Основний випуск № 1701 відкритий з надією на уточнення цього питання. На щастя, оскільки ця двозначність насправді непокоїть мене останнім часом.
unsigned char
-у АБО, а потім продовжувати використовувати ++ptr
звідти, щоб прочитати кожен байт цього тексту ... Але AFAICT, це не визначено як дозволене, тому ми залишилося зробити висновок, що це "ймовірно нормально" з безлічі інших уривків (і багато в чому, просто існування memcpy
) у Стандарті, схожих на головоломку. Що не ідеально. Ну, може, формулювання з часом покращиться. Ось питання про CWG, про який я згадав, але не вистачало місця для посилання - open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1701
unsigned char
є серцем усіх хитрощів. Практично ВСЕ компілятор для ВСІХ платформи а unsigned char
- просто байт і непідписане ціле число (зазвичай) 8 біт, яке можна розглядати як мале ціле число або пакет біт.
У наркоманії, як сказав хтось інший, стандарт не визначає ознаки знаку. тому у вас є 3 різних char
типів: char
, signed char
, unsigned char
.
Якщо вам подобається , використовуючи різні типи довжини конкретного і знаковості, ви , ймовірно , краще з uint8_t
, int8_t
, uint16_t
і т.д. , просто тому , що вони роблять саме те , що вони говорять.
Деякі googling знайшли це , де люди мали дискусію з цього приводу.
Непідписаний значок - це в основному один байт. Отже, ви б використали це, якщо вам потрібен один байт даних (наприклад, можливо, ви хочете використовувати його для встановлення і вимкнення прапорів для передачі функції, як це часто робиться в API Windows).
Непідписаний знак char використовує біт, який зарезервований для знаку звичайного знака, як інше число. Це змінює діапазон на [0 - 255] на відміну від [-128 - 127].
Зазвичай символи без знаку використовуються, коли ви не хочете, щоб знак. Це призведе до різниці, коли ви робите такі зміни, як зміщення бітів (shift поширює знак) та інші речі, коли маєте справу зі знаком як байт, а не використовуєте його як число.
процитував книгу "c програмою для прання":
Класифікатор 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'
, «А» є виконавчі 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