548 Stimmen

Was ist ein Zeichen ohne Vorzeichen?

In C/C++, was eine unsigned char verwendet wird? Wie unterscheidet sie sich von einer normalen char ?

617voto

Fruny Punkte 6263

In C++ gibt es drei deutlich Zeichentypen:

  • char
  • signed char
  • unsigned char

Wenn Sie Zeichentypen verwenden für Text verwenden Sie das unqualifizierte char :

  • es ist der Typ von Zeichenliteralen wie 'a' o '0' (nur in C++, in C ist ihr Typ int )
  • ist der Typ, aus dem C-Zeichenketten wie "abcde"

Es funktioniert auch als Zahlenwert, aber es ist nicht spezifiziert, ob dieser Wert als vorzeichenbehaftet oder vorzeichenlos behandelt wird. Vorsicht bei Zeichenvergleichen durch Ungleichungen - wenn Sie sich allerdings auf ASCII (0-127) beschränken, sind Sie so gut wie sicher.

Wenn Sie Zeichentypen als Zahlen verwenden:

  • signed char die Ihnen Folgendes bietet mindestens den Bereich -127 bis 127. (-128 bis 127 ist üblich)
  • unsigned char die Ihnen Folgendes bietet mindestens den Bereich von 0 bis 255.

"Mindestens", weil der C++-Standard nur den Mindestwertebereich angibt, den jeder numerische Typ abdecken muss. sizeof (char) muss 1 sein (d.h. ein Byte), aber ein Byte könnte theoretisch z.B. 32 Bits umfassen. sizeof würde immer noch seine Größe melden als 1 - was bedeutet, dass Sie könnte haben sizeof (char) == sizeof (long) == 1 .

6 Stimmen

Könnte man 32-Bit-Zeichen und 32-Bit-Ganzzahlen haben und sizeof(int) != sizeof(char) haben, um das zu verstehen? Ich weiß, dass der Standard sagt, dass sizeof(char) == 1 ist, aber basiert die relative sizeof(int) auf dem tatsächlichen Größenunterschied oder dem Unterschied im Bereich?

0 Stimmen

Joseph, die sizeof gibt Ihnen die Größe der Objekt-Darstellung des Typs. wenn Sie sagen, 32bit int, das erste sagt nicht viel. höchstwahrscheinlich meinen Sie die Objekt-Darstellung (das ist die physische Größe - einschließlich aller Padding-Bits).

0 Stimmen

Wenn das der Fall ist, kann sizeof(int) != sizeof(char) nicht wahr sein, weil char/unsigned/signed char alle Bits ihrer Objektdarstellung verwenden, um ihre Werte darzustellen (die so genannte Wertdarstellung)

107voto

Todd Gamblin Punkte 56250

Dies hängt von der Implementierung ab, da der C-Standard NICHT die Vorzeichenhaftigkeit von char . Je nach Plattform kann das Zeichen signed o unsigned Sie müssen also ausdrücklich nachfragen signed char o unsigned char wenn Ihre Implementierung davon abhängt. Verwenden Sie einfach char wenn Sie beabsichtigen, Zeichen aus Zeichenketten darzustellen, da dies dem entspricht, was Ihre Plattform in die Zeichenkette einfügt.

Der Unterschied zwischen signed char y unsigned char ist so, wie man es erwarten würde. Auf den meisten Plattformen, signed char ist eine 8-Bit-Zweierkomplementzahl im Bereich von -128 まで 127 y unsigned char ist eine 8-Bit-Ganzzahl ohne Vorzeichen ( 0 まで 255 ). Beachten Sie, dass die Norm NICHT verlangt, dass char Typen haben 8 Bits, nur dass sizeof(char) return 1 . Sie können die Anzahl der Bits in einem Zeichen mit CHAR_BIT en limits.h . Es gibt heute nur wenige Plattformen, auf denen dies etwas anderes ist als 8 Allerdings.

Es gibt eine schöne Zusammenfassung dieses Themas aquí .

Wie bereits von anderen erwähnt wurde, ist es besser, wenn Sie int8_t y uint8_t wenn Sie wirklich kleine ganze Zahlen darstellen wollen.

3 Stimmen

Vorzeichenbehaftete Zeichen haben nur einen Mindestbereich von -127 bis 127, nicht von -128 bis 127

6 Stimmen

@12431234123412341234123: Technisch gesehen stimmt das, da der C-Standard -127 bis 127 als Mindestbereich definiert. Ich fordere Sie jedoch heraus, eine Plattform zu finden, die keine Zweierkomplement-Arithmetik verwendet. Auf fast jeder modernen Plattform liegt der tatsächliche Bereich für vorzeichenbehaftete Zeichen zwischen -128 und 127.

0 Stimmen

CHAR_BIT muss nach der Norm mindestens 8 Bit betragen.

45voto

Da ich das Gefühl habe, dass es wirklich notwendig ist, möchte ich einige Regeln von C und C++ nennen (sie sind in dieser Hinsicht gleich). Erstens, alle Bits von unsigned char an der Bestimmung des Wertes eines beliebigen unsigned char-Objekts teilnehmen. Zweitens, unsigned char ist ausdrücklich ohne Vorzeichen angegeben.

Ich hatte eine Diskussion mit jemandem darüber, was passiert, wenn man den Wert -1 vom Typ int an unsigned char . Er lehnte die Idee ab, dass die daraus resultierenden unsigned char hat alle Bits auf 1 gesetzt, weil er sich Gedanken über die Vorzeichendarstellung gemacht hat. Aber das war nicht nötig. Aus dieser Regel ergibt sich unmittelbar, dass die Umwandlung das tut, was beabsichtigt ist:

Ist der neue Typ vorzeichenlos, wird der Wert durch wiederholtes Addieren oder Subtrahieren eines Wertes mehr als der Maximalwert, der im neuen Typ dargestellt werden kann, konvertiert, 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 Form der Modulo-Rechnung, die auf dieselbe Regel hinausläuft. Wie auch immer, was ist no garantiert ist, dass alle Bits in der Ganzzahl -1 sind vor der Umwandlung eins. Was haben wir also, damit wir behaupten können, dass die resultierende unsigned char hat alle seine CHAR_BIT Bits auf 1 gesetzt?

  1. Alle Bits sind an der Bestimmung des Wertes beteiligt, d. h. es gibt keine Auffüllbits im Objekt.
  2. Nur einmaliges Hinzufügen UCHAR_MAX+1 まで -1 wird einen Wert im Bereich ergeben, nämlich UCHAR_MAX

Das reicht eigentlich schon! Wann immer Sie also eine unsigned char alle seine Bits eins haben, tun Sie

unsigned char c = (unsigned char)-1;

Daraus folgt auch, dass eine Umwandlung no nur das Abschneiden von Bits höherer Ordnung. Das glückliche Ereignis für Zweierkomplement ist, dass es sich dort nur um eine Verkürzung handelt, aber das Gleiche gilt nicht unbedingt für andere Zeichendarstellungen.

2 Stimmen

Warum verwenden Sie nicht einfach UCHAR_MAX ?

1 Stimmen

Porque (unsigned type)-1 ist eine Art Redewendung. ~0 ist es nicht.

1 Stimmen

Wenn ich etwas wie dieses habe int x = 1234 y char *y = &x . Binäre Darstellung von 1234 es 00000000 00000000 00000100 11010010 . Mein Rechner ist Little Endian, also kehrt er es um und speichert es im Speicher. 11010010 00000100 00000000 00000000 LSB kommt zuerst. Jetzt Hauptteil . wenn ich benutze printf("%d" , *p) . printf liest das erste Byte 11010010 nur die Ausgabe ist -46 pero 11010010 es 210 warum wird dann gedruckt -46 . Ich bin wirklich verwirrt, ich vermute, dass irgendeine Char-to-Integer-Promotion etwas tut, aber ich weiß es nicht.

33voto

Zachary Garrett Punkte 2468

Wie zum Beispiel Verwendungen von unsigned char :

unsigned char wird häufig in der Computergrafik verwendet, die sehr oft (aber nicht immer) jeder Farbkomponente ein einzelnes Byte zuordnet. Üblicherweise wird eine RGB- (oder RGBA-) Farbe mit 24 (oder 32) Bits dargestellt, die jeweils ein unsigned char . Desde unsigned char Werte in den Bereich [0,255] fallen, werden die Werte in der Regel wie folgt interpretiert:

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

Das Ergebnis wäre also RGB-Rot als (255,0,0) -> (100% Rot, 0% Grün, 0% Blau).

Warum nicht eine signed char ? Arithmetik und Bitverschiebung werden problematisch. Wie bereits erklärt, ist eine signed char Die Reichweite wird im Wesentlichen um -128 verschoben. Eine sehr einfache und naive (meist nicht genutzte) Methode zur Umwandlung von RGB in Graustufen besteht darin, den Durchschnitt aller drei Farbkomponenten zu bilden, was jedoch zu Problemen führt, wenn die Werte der Farbkomponenten negativ sind. Rot (255, 0, 0) wird zu (85, 85, 85) gemittelt, wenn man unsigned char Arithmetik. Wären die Werte jedoch signed char s (127,-128,-128), würden wir am Ende (-99, -99, -99) erhalten, was in unserem Fall (29, 29, 29) wäre. unsigned char Raum, was nicht korrekt ist.

1 Stimmen

Vielleicht übersehe ich etwas, aber ich verstehe nicht, wie eine feste Verschiebung einen arithmetischen Durchschnitt brechen kann. Der Durchschnitt von 127, -128 und -128 ist -43, nicht -99. Wenn Sie 128 dazu addieren, erhalten Sie 85, was dasselbe ist wie in Ihrem Beispiel ohne Vorzeichen.

13voto

James Hopkin Punkte 13389

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

char entspricht je nach Compiler entweder signed char oder unsigned char, ist aber ein eigener Typ.

Wenn Sie Strings im C-Stil verwenden, benutzen Sie einfach char . Wenn Sie Zeichen für die Arithmetik verwenden müssen (ziemlich selten), geben Sie aus Gründen der Portabilität ausdrücklich vorzeichenbehaftete oder vorzeichenlose Zeichen an.

0 Stimmen

Wie konvertiert man "unsigned char *" mit pybind11 in Python-Bytes?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X