it-swarm-eu.dev

Was ist ein nicht signierter Char?

Wofür wird in C/C++ ein unsigned char verwendet? Wie unterscheidet es sich von einem normalen char?

440
Landon Kuhn

In C++ gibt es drei unterschiedliche Zeichentypen:

  • char
  • signed char
  • unsigned char

Wenn Sie Zeichentypen für Text verwenden, verwenden Sie das nicht qualifizierte char:

  • es ist die Art von Zeichenliteralen wie 'a' oder '0'.
  • es ist der Typ, aus dem C-Strings wie "abcde" bestehen.

Es funktioniert auch als Zahlenwert, es ist jedoch nicht festgelegt, ob dieser Wert als vorzeichenbehaftet oder nicht vorzeichenbehaftet behandelt wird. Passen Sie auf Zeichenvergleiche durch Ungleichungen auf - auch wenn Sie sich auf ASCII (0-127) beschränken, sind Sie in etwa sicher.

Wenn Sie Zeichentypen als Zahlen verwenden, verwenden Sie:

  • signed char, wodurch Sie mindestens den Bereich von -127 bis 127 erhalten. (-128 bis 127 ist üblich)
  • unsigned char, wodurch Sie mindestens den Bereich von 0 bis 255 erhalten.

"Zumindest", da der C++ - Standard nur den minimalen Wertebereich angibt, den jeder numerische Typ abdecken muss. sizeof (char) muss 1 sein (d. h. ein Byte), aber ein Byte könnte theoretisch zum Beispiel 32 Bits sein. sizeof würde immer noch die Größe von 1 angeben - was bedeutet, dass Sie eine sizeof (char) == sizeof (long) == 1 haben könnten.

520
Fruny

Dies ist implementierungsabhängig, da der C-Standard NICHT die Vorzeichen von char definiert. Je nach Plattform kann char signed oder unsigned sein. Sie müssen daher explizit nach signed char oder unsigned char fragen, wenn Ihre Implementierung davon abhängt. Verwenden Sie einfach char, wenn Sie Zeichen aus Zeichenfolgen darstellen möchten, da dies mit dem übereinstimmt, was Ihre Plattform in die Zeichenfolge einfügt.

Der Unterschied zwischen signed char und unsigned char ist wie erwartet. Auf den meisten Plattformen ist signed char eine 8-Bit-Zweierkomplementzahl, die von -128 bis 127 reicht, und unsigned char ist eine 8-Bit-Ganzzahl ohne Vorzeichen (0 bis 255). Beachten Sie, dass der Standard NICHT erfordert, dass char -Typen 8 Bits haben, sondern nur, dass sizeof(char)1 zurückgibt. Sie können die Anzahl der Bits in einem Zeichen mit CHAR_BIT in limits.h ermitteln. Es gibt heutzutage nur wenige Plattformen, auf denen dies nicht nur 8 ist.

Es gibt eine nette Zusammenfassung dieser Ausgabe hier .

Wie andere bereits erwähnt haben, ist es besser, int8_t und uint8_t zu verwenden, wenn Sie wirklich kleine ganze Zahlen darstellen möchten.

83
Todd Gamblin

Da ich der Meinung bin, dass es wirklich notwendig ist, möchte ich nur einige Regeln für C und C++ angeben (in dieser Hinsicht sind sie die gleichen). Zunächst nehmen alle Bits von unsigned char an der Bestimmung des Werts eines vorzeichenlosen Zeichenobjekts teil. Zweitens wird unsigned char ausdrücklich ohne Vorzeichen angegeben.

Jetzt hatte ich eine Diskussion mit jemandem darüber, was passiert, wenn Sie den Wert -1 vom Typ int in unsigned char konvertieren. Er lehnte die Idee ab, dass das resultierende unsigned char alle seine Bits auf 1 gesetzt hat, weil er sich Sorgen um die Darstellung von Vorzeichen machte. Muss er aber nicht. Aus dieser Regel folgt sofort, dass die Konvertierung das tut, was beabsichtigt ist:

Wenn der neue Typ kein Vorzeichen hat, wird der Wert konvertiert, indem wiederholt ein Wert mehr als der Maximalwert, der im neuen Typ dargestellt werden kann, addiert oder subtrahiert wird, bis der Wert im Bereich des neuen Typs liegt. (6.3.1.3p2 in einem C99-Entwurf)

Das ist eine mathematische Beschreibung. C++ beschreibt es in Modulo-Berechnungen, die nach derselben Regel ablaufen. Auf jeden Fall ist nicht garantiert, dass alle Bits in der Ganzzahl -1 vor der Konvertierung eins sind. Was haben wir also, damit wir behaupten können, dass für den resultierenden unsigned char alle CHAR_BIT Bits auf 1 gesetzt sind?

  1. Alle Bits sind an der Bestimmung ihres Werts beteiligt, dh, im Objekt treten keine Füllbits auf.
  2. Das einmalige Hinzufügen von UCHAR_MAX+1 zu -1 ergibt einen Wert im Bereich, nämlich UCHAR_MAX.

Das reicht eigentlich! Also, wann immer Sie einen unsigned char haben möchten, der alle seine Bits eins hat, tun Sie dies

unsigned char c = (unsigned char)-1;

Daraus folgt auch, dass eine Konvertierung nicht nur höherwertige Bits abschneidet. Das glückliche Ereignis für Zweierkomplement ist, dass es dort nur eine Kürzung ist, aber dasselbe gilt nicht unbedingt für andere Zeichendarstellungen.

Wie zum Beispiel Verwendungen von nsigned char:

nsigned char wird häufig in Computergrafiken verwendet, bei denen (wenn auch nicht immer) jeder Farbkomponente ein einzelnes Byte zugewiesen wird. Es ist üblich, eine RGBoder RGBA-) Farbe als 24 (oder 32) Bits darzustellen, wobei jedes ein --- (vorzeichenloses Zeichen ist. Da vorzeichenlose Zeichen Werte im Bereich [0,255] liegen, werden die Werte normalerweise folgendermaßen interpretiert:

  • 0 bedeutet das völlige Fehlen einer bestimmten Farbkomponente.
  • 255 bedeutet 100% eines gegebenen Farbpigments.

Sie erhalten also RGB-Rot als (255,0,0) -> (100% Rot, 0% Grün, 0% Blau).

Warum nicht ein signiertes Zeichen verwenden? Arithmetik und Bitverschiebung werden problematisch. Wie bereits erläutert, wird der Bereich von a vorzeichenbehaftetes Zeichen wesentlich um -128 verschoben. Eine sehr einfache und naive (meist nicht verwendete) Methode zur Konvertierung von RGB in Graustufen besteht darin, alle drei Farbkomponenten zu mitteln. Dies führt jedoch zu Problemen, wenn die Werte der Farbkomponenten negativ sind. Rot (255, 0, 0) ergibt einen Durchschnitt von (85, 85, 85), wenn vorzeichenloses Zeichen Arithmetik verwendet wird. Wenn die Werte jedoch vorzeichenbehaftetes Zeichen s (127, -128, -128) wären, erhalten wir (-99, -99, -99), was (29, 29, 29) in unserem nsigned char Raum, der falsch ist.

24
Zachary Garrett

Wenn Sie ein Zeichen als kleine Ganzzahl verwenden möchten, ist dies am sichersten mit den Typen int8_t und uint8_t möglich.

12
jbleners

unsigned char nimmt nur positive Werte an .... wie bis 255

wohingegen

signed char nimmt sowohl positive als auch negative Werte an .... wie - 128 bis + 127

6
munna

char und unsigned char sind nicht auf allen Plattformen garantiert 8-Bit-Typen. Sie sind garantiert 8-Bit-Typen oder größer. Einige Plattformen haben 9-Bit-, 32-Bit- oder 64-Bit-Bytes . Die gängigsten Plattformen (Windows, Mac, Linux x86 usw.) haben jedoch 8-Bit-Bytes.

6
bk1e

signed char hat einen Bereich von -128 bis 127; unsigned char hat einen Bereich von 0 bis 255.

char entspricht je nach Compiler entweder dem Zeichen mit oder ohne Vorzeichen, ist jedoch ein anderer Typ.

Wenn Sie Zeichenfolgen im C-Stil verwenden, verwenden Sie einfach char. Wenn Sie Zeichen für die Arithmetik verwenden müssen (ziemlich selten), geben Sie aus Gründen der Portabilität explizit signiert oder unsigniert an.

5
James Hopkin

Ein vorzeichenloses Zeichen ist ein (vorzeichenloser) Bytewert (0 bis 255). Sie denken vielleicht, dass "char" ein "Charakter" ist, aber es ist wirklich ein numerischer Wert. Das reguläre "char" ist signiert, Sie haben also 128 Werte und diese Werte werden Zeichen mit der ASCII-Codierung zugeordnet. In beiden Fällen ist das, was Sie im Speicher speichern, ein Bytewert.

4
Zac Gochenour

In Bezug auf direkte Werte wird ein reguläres Zeichen verwendet, wenn bekannt ist, dass die Werte zwischen CHAR_MIN und CHAR_MAX liegen, während ein vorzeichenloses Zeichen den doppelten Bereich am positiven Ende bereitstellt. Wenn CHAR_BIT beispielsweise 8 ist, beträgt der Bereich für reguläres char garantiert nur [0, 127] (da signiert oder nicht signiert sein kann), während unsigned char [0] ist , 255] und signed char sind [-127, 127].

In Bezug auf die Verwendungszwecke ermöglichen die Standards die direkte Konvertierung von POD-Objekten (Plain Old Data) in ein Array von Zeichen ohne Vorzeichen. Auf diese Weise können Sie die Darstellung und die Bitmuster des Objekts untersuchen. Die gleiche Garantie für sicheres Punning besteht nicht für char oder signed char.

4
Julienne Walker

Wenn Sie verschiedene Arten von Längen und Signaturen bevorzugen, sind Sie mit uint8_t, int8_t, uint16_t usw. wahrscheinlich besser dran, weil sie genau das tun, was sie sagen.

2
Dark Shikari

Ein vorzeichenloses Zeichen verwendet das Bit, das für das Vorzeichen eines regulären Zeichens reserviert ist, als eine andere Zahl. Dies ändert den Bereich auf [0 - 255] im Gegensatz zu [-128 - 127].

Im Allgemeinen werden Zeichen ohne Vorzeichen verwendet, wenn Sie kein Zeichen möchten. Dies macht einen Unterschied, wenn Sie z. B. Bits verschieben (Shift erweitert das Vorzeichen) und andere Dinge, wenn Sie ein Zeichen als Byte behandeln, anstatt es als Zahl zu verwenden.

2
JasonOfEarth

zeichen ohne Vorzeichen ist das Herzstück aller kleinen Tricks. In fast ALL-Compiler für ALL-Plattform ist ein nicht signiertes Zeichen einfach ein BYTE. Eine vorzeichenlose ganze Zahl von (normalerweise) 8 Bit. das kann als eine kleine ganze Zahl oder ein Pack von Bits behandelt werden.

In der Sucht, wie jemand anderes gesagt hat, definiert der Standard nicht das Zeichen eines Zeichens. Sie haben also 3 verschiedene "char" -Typen: char, signed char, unsigned char.

2
ugasoft

Einige googeln fanden this , wo die Leute eine Diskussion darüber hatten.

Ein vorzeichenloses Zeichen ist im Grunde ein einzelnes Byte. Sie würden dies also verwenden, wenn Sie ein Datenbyte benötigen (z. B. möchten Sie damit Flags aktivieren oder deaktivieren, die an eine Funktion übergeben werden sollen, wie dies in der Windows-API häufig der Fall ist).

1
dbrien

zeichen ohne Vorzeichen nehmen nur positive Werte an: 0 bis 255 Zeichen mit Vorzeichen nehmen positive und negative Werte an: -128 bis +127

0
NL628

zitat aus dem Buch "the c programming laugage":

Das Qualifikationsmerkmal signed oder unsigned kann auf char oder eine beliebige Ganzzahl angewendet werden. vorzeichenlose Zahlen sind immer positiv oder null und befolgen die Gesetze des arithmetischen Moduls 2 ^ n, wobei n die Anzahl der Bits im Typ ist. Wenn Zeichen beispielsweise 8 Bit lang sind, haben vorzeichenlose Zeichenvariablen Werte zwischen 0 und 255, während vorzeichenbehaftete Zeichen Werte zwischen -128 und 127 haben (auf einem Zweierkomplement-Computer) -abhängige, aber druckbare Zeichen sind immer positiv.

0
ZhaoGang