Для чого C / C ++ для чого unsigned charвикористовується? Чим він відрізняється від звичайного char?
Для чого C / C ++ для чого unsigned charвикористовується? Чим він відрізняється від звичайного char?
Відповіді:
У C ++ є три різних типи символів:
charsigned charunsigned 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 00000000LSB приходить першим. Тепер основна частина. якщо я використовую 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 chars (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