it-swarm-eu.dev

Co je znak bez znaménka?

K čemu se v C/C++ používá unsigned char? Jak se liší od běžného char?

433
Landon Kuhn

V C++ existují tři odlišné typy znaků:

  • charname__
  • signed char
  • unsigned char

Pokud používáte textové znaky pro text , použijte nekvalifikovaný charname__:

  • je to typ znakových literálů jako 'a' nebo '0'.
  • je to typ, který tvoří řetězce C jako "abcde"

Funguje také jako číselná hodnota, ale není specifikováno, zda je s touto hodnotou zacházeno jako s podepsanou nebo nepodepsanou hodnotou. Dávejte si pozor na porovnání postav prostřednictvím nerovností - i když pokud se omezíte na ASCII (0-127), jste jen v bezpečí.

Pokud používáte typy znaků jako čísla , použijte:

  • signed char, což vám dává alespoň rozsah -127 až 127. (-128 až 127 je běžné)
  • unsigned char, což vám dává alespoň rozsah 0 až 255.

„Alespoň“, protože standard C++ poskytuje pouze minimální rozsah hodnot, které musí každý číselný typ pokrýt. sizeof (char) musí být 1 (tj. jeden byte), ale byte by teoreticky mohl být například 32 bitů. sizeofNAME__ BY I NADÁLE VYKAZOVAL SVOU VELIKOST JAKO 1 - což znamená, že můžete mít sizeof (char) == sizeof (long) == 1.

513
Fruny

To je závislé na implementaci, protože standard C NEJSOU definován podepsanou char. V závislosti na platformě může být znakem signed nebo unsigned, takže musíte explicitně požádat o signed char nebo unsigned char, pokud vaše implementace na tom závisí. Stačí použít char, pokud chcete reprezentovat znaky z řetězců, protože to bude odpovídat tomu, co vaše platforma vloží do řetězce.

Rozdíl mezi signed char a unsigned char je očekávaný. Na většině platforem bude signed char 8-bitové dvoučíselné číslo doplňku od -128 do 127 a unsigned char bude 8bitové celé číslo bez znaménka (0255). Všimněte si, že standard NEVYŽADUJE, aby typy char měly 8 bitů, pouze sizeof(char) vrátí 1. Počet bitů v znaku můžete získat pomocí CHAR_BIT v limits.h. Dnes existuje jen málo, pokud vůbec nějaké platformy, kde to bude něco jiného než 8.

Existuje pěkné shrnutí tohoto čísla zde .

Jak již uvedli ostatní, od doby, kdy jsem to zveřejnil, je lepší používat int8_t a uint8_t, pokud opravdu chcete reprezentovat malá celá čísla.

81
Todd Gamblin

Protože mám pocit, že je to opravdu požadováno, chci jen uvést některá pravidla C a C++ (v tomto ohledu jsou stejná). Nejprve se všechny bity z unsigned char účastní stanovení hodnoty, pokud se jedná o nepodepsaný znakový objekt. Za druhé, unsigned char je výslovně uvedeno bez podpisu.

Nyní jsem s někým diskutoval o tom, co se stane, když převedete hodnotu -1 typu int na unsigned char. Odmítl myšlenku, že výsledný unsigned char má všechny své bity nastaveny na 1, protože se obával reprezentace znaménka. Ale nemusí. Z tohoto pravidla okamžitě vyplývá, že převod provede to, co je zamýšleno:

Pokud je nový typ nepodepsán, je hodnota převedena opakovaným přidáváním nebo odečtením více než maximální hodnoty, kterou lze v novém typu reprezentovat, dokud není hodnota v rozsahu nového typu. (6.3.1.3p2 v konceptu C99)

To je matematický popis. C++ to popisuje z hlediska modulo počtu, který dává stejné pravidlo. Každopádně je zaručeno nikoli, že všechny bity v celém čísle -1 jsou před konverzí jeden. Co tedy máme, abychom mohli tvrdit, že výsledný unsigned char má všechny své CHAR_BIT bity změněné na 1?

  1. Všechny bity se účastní určování jeho hodnoty - to znamená, že v objektu se nevyskytují žádné výplňové bity.
  2. Přidání pouze jednoho času UCHAR_MAX+1 do -1 přinese hodnotu v rozsahu, konkrétně UCHAR_MAX

To vlastně stačí! Takže kdykoli budete chtít mít unsigned char, který bude mít všechny své bity jeden, tak ano

unsigned char c = (unsigned char)-1;

Z toho také vyplývá, že převod je ne zkrácením bitů vyššího řádu. Štastnou událostí pro doplněk dvo je to, že se jedná pouze o zkrácení, ale totéž nemusí nutně platit pro ostatní reprezentace znaménka.

35

Například použití nepodepsané znaky:

nsigned char se často používá v počítačové grafice, která velmi často (i když ne vždy) přiřadí každému bajtovému komponentu jeden byte. Je běžné vidět barvu RGB (nebo RGBA) představovanou jako 24 (nebo 32) bitů, každý nepodepsané znaky. Protože hodnoty nsigned char spadají do rozsahu [0,255], hodnoty jsou obvykle interpretovány jako:

  • 0 znamená celkový nedostatek dané barevné složky.
  • 255 znamená 100% daného barevného pigmentu.

Takže byste skončili s RGB červenou jako (255,0,0) -> (100% červená, 0% zelená, 0% modrá).

Proč nepoužívat podepsané znaky? Aritmetické a bitové řazení se stává problematickým. Jak již bylo vysvětleno, rozsah podepsané char je v podstatě posunut o -128. Velmi jednoduchá a naivní (většinou nepoužitá) metoda pro převod RGB na stupně šedi je průměrovat všechny tři barevné složky, ale to se stává problémem, když jsou hodnoty barevných složek záporné. Červené (255, 0, 0) průměry na (85, 85, 85) při použití bez znaménka aritmetika. Pokud by však hodnoty byly podepsané char s (127, -128, -128), skončili bychom s (-99, -99, -99), což by bylo (29, 29, 29) v našem nepodepsaném znak prostoru, což je nesprávné.

24
Zachary Garrett

Pokud chcete použít znak jako malé celé číslo, nejbezpečnější způsob, jak to udělat, je u typů int8_t a uint8_t.

12
jbleners

signed char má rozsah -128 až 127; unsigned char má rozsah 0 až 255.

char bude v závislosti na kompilátoru ekvivalentní buď podepsané nebo nepodepsané znaky, ale je to odlišný typ.

Pokud používáte řetězce ve stylu C, použijte pouze char. Pokud potřebujete použít znak pro aritmetiku (docela vzácný), zadejte výslovně podepsané nebo nepodepsané pro přenositelnost.

5
James Hopkin

char a unsigned char nezaručují, že budou na všech platformách 8bitové typy - je zaručeno, že budou 8bitové nebo větší. Některé platformy mají 9bitové, 32bitové nebo 64bitové bajty . Nejběžnější platformy dnes (Windows, Mac, Linux x86 atd.) Však mají 8bitové bajty.

5
bk1e

Pokud jde o přímé hodnoty, používá se normální znak, pokud je známo, že hodnoty jsou mezi CHAR_MIN a CHAR_MAX, zatímco nepodepsané char poskytuje dvojnásobný rozsah na kladném konci. Například pokud CHAR_BIT je 8, rozsah běžného char je zaručen pouze [0, 127] (protože může být podepsán nebo nepodepsán), zatímco unsigned char bude [0, 255] a signed char bude [-127, 127 ].

Z hlediska toho, k čemu se používá, umožňují standardy přímý převod objektů POD (obyčejná stará data) na řadu nepodepsaných znaků. To vám umožní prozkoumat reprezentaci a bitové vzory objektu. Stejná záruka bezpečného typu penningu neexistuje pro znak char nebo podepsaný znak.

4
Julienne Walker

unsigned char bere pouze kladné hodnoty .... jako až 255

zatímco

signed char bere kladné i záporné hodnoty .... jako - 128+ 127

4
munna

Neznačený znak je (nepodepsaná) bajtová hodnota (0 až 255). Možná uvažujete o „char“, pokud jde o „charakter“, ale je to opravdu číselná hodnota. Normální znak "char" je podepsán, takže máte 128 hodnot a tyto hodnoty se mapují na znaky pomocí kódování ASCII. Ale v obou případech je to, co ukládáte do paměti, bajtová hodnota.

3
Zac Gochenour

Pokud chcete používat různé typy specifické délky a signness, pravděpodobně máte lepší uint8_t, int8_t, uint16_t atd. Jednoduše proto, že dělají přesně to, co říkají.

2
Dark Shikari

Nepřihlášený znak používá bit, který je vyhrazen pro znak běžného znaku, jako jiné číslo. Tím se změní rozsah na [0 - 255] na rozdíl od [-128 - 127].

Obecně se nepoužívané znaky používají, když nechcete podepsat. To bude mít vliv při provádění věcí, jako je posunování bitů (posun rozšiřuje znaménko) a dalších věcí, když se jedná o char jako o byte, než o jeho použití jako čísla.

2
JasonOfEarth

nepodepsané char je srdcem všech kousků. V téměř ALL kompilátoru pro VŠECHNY platformy je nepodepsaný znak jednoduše BYTE. Neoznačené celé číslo (obvykle) 8 bitů. které lze považovat za malé celé číslo nebo jako balíček bitů.

Navíc, jak řekl někdo jiný, standard nedefinuje znak char. takže máte 3 odlišné typy „char“: char, signed char, unsigned char.

2
ugasoft

Někteří googling našli toto , kde o tom lidé diskutovali.

Nepřihlášený znak je v podstatě jediný bajt. To byste tedy použili, pokud potřebujete jeden bajt dat (například, možná budete chtít použít k nastavení příznaků zapnutí a vypnutí, které budou předány funkci, jak se často děje v rozhraní Windows API).

1
dbrien

nepodepsané char bere pouze kladné hodnoty: 0 až 255 podepsané char bere kladné a záporné hodnoty: -128 až +127

0
NL628

citován z knihy „programovací laugage“:

Kvalifikátor signed nebo unsigned lze použít na znak nebo celé číslo. nepodepsaná čísla jsou vždy kladná nebo nulová a dodržují zákony aritmetického modulo 2 ^ n, kde n je počet bitů v typu. Například, pokud chars je 8 bitů, nepodepsané char proměnné mají hodnoty mezi 0 a 255, zatímco podepsané chars mají hodnoty mezi -128 a 127 (ve dvou doplňkovém stroji). Zda jsou prosté znaky podepsané nebo nepodepsané, je stroj -závislé, ale tisknutelné znaky jsou vždy pozitivní.

0
ZhaoGang