Wofür unsigned charwird in C / C ++ ein verwendet? Wie unterscheidet es sich von einem normalen char?
Wofür unsigned charwird in C / C ++ ein verwendet? Wie unterscheidet es sich von einem normalen char?
Antworten:
In C ++ gibt es drei verschiedene Zeichentypen:
charsigned charunsigned charWenn Sie Zeichentypen für Text verwenden , verwenden Sie Folgendes char:
'a'oder '0'."abcde"Es funktioniert auch als Zahlenwert, es ist jedoch nicht angegeben, ob dieser Wert als signiert oder nicht signiert behandelt wird. Hüten Sie sich vor Charaktervergleichen durch Ungleichungen - obwohl Sie, wenn Sie sich auf ASCII (0-127) beschränken, fast sicher sind.
Wenn Sie Zeichentypen als Zahlen verwenden , verwenden Sie:
signed char, was Ihnen mindestens den Bereich von -127 bis 127 gibt. (-128 bis 127 ist üblich)unsigned char, was Ihnen mindestens den Bereich von 0 bis 255 gibt."Zumindest", da der C ++ - Standard nur den Mindestwertebereich angibt, den jeder numerische Typ abdecken muss. sizeof (char)muss 1 sein (dh ein Byte), aber ein Byte könnte theoretisch beispielsweise 32 Bit sein. sizeofwäre noch seine Größe berichten wie1 - was bedeutet , dass Sie könnte haben sizeof (char) == sizeof (long) == 1.
sizeofda es sich nicht um eine Funktion, sondern um einen Operator handelt. Es ist imho noch besser, die Klammer wegzulassen, wenn man die Größe einer Variablen nimmt. sizeof *poder sizeof (int). Dies macht schnell klar, ob es sich um einen Typ oder eine Variable handelt. Ebenso ist es überflüssig, nach Klammern zu setzen return. Es ist keine Funktion.
char: Es ist die Art von Zeichenliteralen wie 'a'oder '0'." ist wahr in C ++ aber nicht C. In C 'a'ist ein int.
Dies ist implementierungsabhängig, da der C-Standard NICHT die Signatur von definiert char. Je nach Plattform kann char signedoder sein unsigned, daher müssen Sie explizit nachfragen signed charoder unsigned charob Ihre Implementierung davon abhängt. Verwenden charSie diese Option nur, 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 charund unsigned charist wie erwartet. Auf den meisten Plattformen signed charwird eine 8-Bit-Zweierkomplementzahl von reichen-128 bis 127und unsigned chareine 8-Bit-Ganzzahl ohne Vorzeichen ( 0bis 255). Beachten Sie, dass der Standard NICHT verlangt, dass charTypen 8 Bit haben, sondern nur diese sizeof(char)Rückgabe 1. Sie können die Anzahl der Bits in einem Zeichen mit CHAR_BITin ermitteln limits.h. Es gibt heutzutage nur wenige Plattformen, auf denen dies etwas anderes sein 8wird.
Es gibt eine schöne Zusammenfassung dieses Problem hier .
Wie andere erwähnt haben , da ich dies geschrieben, du bist besser dran mit int8_tund uint8_twenn Sie wirklich kleine ganze Zahlen darstellen wollen.
CHAR_BITDer Standard muss mindestens 8 Bit betragen.
Da ich der Meinung bin, dass dies wirklich erforderlich ist, möchte ich nur einige Regeln für C und C ++ angeben (sie sind in dieser Hinsicht gleich). Zuerst werden alle Bits der unsigned charTeilnahme den Wert , wenn jeder unsigned char Objekt zu bestimmen. Zweitens unsigned charwird ausdrücklich ohne Vorzeichen angegeben.
Jetzt hatte ich eine Diskussion mit jemandem darüber, was passiert, wenn Sie den Wert -1vom Typ int in konvertieren unsigned char. Er lehnte die Idee ab, dass das Ergebnis unsigned charalle seine Bits auf 1 gesetzt hat, weil er sich Sorgen um die Darstellung der Zeichen machte. Aber das muss er nicht. Aus dieser Regel folgt unmittelbar, dass die Konvertierung das tut, was beabsichtigt ist:
Wenn der neue Typ nicht signiert ist, wird der Wert konvertiert, indem wiederholt mehr als der Maximalwert addiert oder subtrahiert wird, der im neuen Typ dargestellt werden kann, bis der Wert im Bereich des neuen Typs liegt. (
6.3.1.3p2in einem C99-Entwurf)
Das ist eine mathematische Beschreibung. C ++ beschreibt es mit Modulo-Kalkül, das der gleichen Regel entspricht. Was jedoch nicht garantiert ist, ist, dass alle Bits in der Ganzzahl -1vor der Konvertierung eins sind. Was haben wir also, damit wir behaupten können, dass das Ergebnis unsigned charalle seine CHAR_BITBits auf 1 gesetzt hat?
UCHAR_MAX+1zu-1 erhalten Sie einen Wert im Bereich, nämlichUCHAR_MAXDas reicht eigentlich! Also, wann immer Sie wollen, unsigned chardass alle seine Teile eins haben, tun Sie es
unsigned char c = (unsigned char)-1;
Daraus folgt auch, dass eine Konvertierung nicht nur Bits höherer Ordnung abschneidet. Das glückliche Ereignis für das Zweierkomplement ist, dass es dort nur eine Kürzung ist, aber dasselbe gilt nicht unbedingt für andere Zeichendarstellungen.
UCHAR_MAX?
(unsigned type)-1es eine Art Redewendung ist. ~0ist nicht.
int x = 1234und char *y = &x. Binäre Darstellung von 1234 ist 00000000 00000000 00000100 11010010. Meine Maschine ist Little Endian, also kehrt sie es um und das Speichern im Speicher 11010010 00000100 00000000 00000000LSB steht an erster Stelle. Jetzt Hauptteil. wenn ich benutze printf("%d" , *p). printflesen werden erste Byte ist 11010010der Ausgang nur , -46sondern 11010010ist 210so , warum gedruckt wird es -46. Ich bin wirklich verwirrt, ich denke, ein Zeichen für eine ganzzahlige Werbung macht etwas, aber ich weiß es nicht.
Wie zum Beispiel die Verwendung von nicht signiertem Zeichen :
unsigned charwird häufig in Computergrafiken verwendet, die sehr oft (wenn auch nicht immer) jeder Farbkomponente ein einzelnes Byte zuweisen. Es ist üblich, eine RGB- (oder RGBA-) Farbe zu sehen, die als 24 (oder 32) Bits dargestellt wird unsigned char. Da die unsigned charWerte in den Bereich [0,255] fallen, werden die Werte normalerweise wie folgt interpretiert:
Sie würden also RGB-Rot als (255,0,0) -> (100% Rot, 0% Grün, 0% Blau) erhalten.
Warum nicht ein signed char? Arithmetik und Bitverschiebung werden problematisch. Wie bereits erläutert, signed charist der Bereich von a im Wesentlichen um -128 verschoben. Eine sehr einfache und naive (meist nicht verwendete) Methode zum Konvertieren von RGB in Graustufen besteht darin, alle drei Farbkomponenten zu mitteln. Dies ist jedoch problematisch, wenn die Werte der Farbkomponenten negativ sind. Rot (255, 0, 0) ergibt bei Verwendung der unsigned charArithmetik einen Durchschnittswert von (85, 85, 85) . Wenn die Werte jedoch signed chars (127, -128, -128) wären, würden wir am Ende (-99, -99, -99) haben, was (29, 29, 29) in unserem unsigned charRaum wäre, was falsch ist .
Wenn Sie ein Zeichen als kleine Ganzzahl verwenden möchten, ist es am sichersten, dies mit den Typen int8_tund zu tun uint8_t.
int8_tund uint8_tsind optional und nicht auf Architekturen definiert, bei denen die Bytegröße nicht genau 8 Bit beträgt. Umgekehrt signed charund unsigned charsind immer verfügbar und halten garantiert mindestens 8 Bit. Es mag ein üblicher Weg sein, aber nicht der sicherste .
signed charund zu bleiben unsigned char? Oder würden Sie in diesem speziellen Fall eine bessere "sicherere" Alternative empfehlen? Zum Beispiel, um bei den "echten" Ganzzahltypen zu bleiben signed intund unsigned intstattdessen aus irgendeinem Grund?
signed charund unsigned charist für alle konformen Implementierungen portierbar und spart Speicherplatz, kann jedoch zu einer gewissen Erhöhung der Codegröße führen. In einigen Fällen würde man mehr Speicherplatz sparen, indem kleine Werte in Bitfeldern oder einzelnen Bits regulärer Ganzzahltypen gespeichert werden. Es gibt keine absolute Antwort auf diese Frage, die Relevanz dieses Ansatzes hängt vom jeweiligen Einzelfall ab. Und diese Antwort spricht die Frage sowieso nicht an.
char und unsigned char es wird nicht garantiert, dass es sich auf allen Plattformen um 8-Bit-Typen handelt - es wird garantiert, dass sie 8-Bit oder größer sind. Einige Plattformen verfügen über 9-Bit-, 32-Bit- oder 64-Bit-Bytes . Die heute gängigsten Plattformen (Windows, Mac, Linux x86 usw.) haben jedoch 8-Bit-Bytes.
signed char hat einen Bereich von -128 bis 127; unsigned charhat einen Bereich von 0 bis 255.
char wird je nach Compiler entweder einem signierten oder einem nicht signierten Zeichen entsprechen, ist jedoch ein eindeutiger 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 für die Portabilität explizit signiert oder nicht signiert an.
An unsigned charist ein vorzeichenloser Bytewert (0 bis 255). Sie denken vielleicht daran char, ein "Zeichen" zu sein, aber es ist wirklich ein numerischer Wert. Der reguläre charWert ist signiert, sodass Sie 128 Werte haben. Diese Werte werden Zeichen mit ASCII-Codierung zugeordnet. In beiden Fällen ist das, was Sie im Speicher speichern, ein Bytewert.
In Bezug auf direkte Werte wird ein reguläres Zeichen verwendet, wenn bekannt ist, dass die Werte zwischen CHAR_MINund CHAR_MAXwährend ein vorzeichenloses Zeichen den doppelten Bereich am positiven Ende liefert. Wenn beispielsweise CHAR_BIT8 ist, charwird garantiert, dass der reguläre Bereich nur [0, 127] beträgt (da er signiert oder nicht signiert sein kann), während unsigned charer [0, 255] und signed char[-127, 127] ist.
In Bezug auf das, wofür es verwendet wird, ermöglichen die Standards, dass Objekte von POD (einfache alte Daten) direkt in ein Array von Zeichen ohne Vorzeichen konvertiert werden. Auf diese Weise können Sie die Darstellung und die Bitmuster des Objekts untersuchen. Die gleiche Garantie für sicheres Punnen besteht nicht für char oder signiertes char.
unsigned char, nicht als spezifisches Array , und jede "Konvertierung" wird nur formal definiert, indem vom Objekt in ein reales, deklariertes Array von & kopiert wird und dieses dann überprüft wird. Es ist nicht klar, ob das ODER direkt als solches Array neu interpretiert werden kann, mit den zulässigen Zeigerarithmetiken, dh ob "Sequenz" "Array" in dieser Verwendung. Es gibt ein Kernproblem Nr. 1701, in der Hoffnung, dies zu klären. Zum Glück, denn diese Zweideutigkeit nervt mich in letzter Zeit wirklich. unsigned char==
unsigned chardes OP nehmen und dann ++ptrvon dort aus jedes Byte davon lesen können ... aber AFAICT, es ist nicht speziell als erlaubt definiert, also sind wir es links zu schließen, dass es "wahrscheinlich in Ordnung" aus vielen anderen Passagen (und in vielerlei Hinsicht der bloßen Existenz von memcpy) im Standard ist, ähnlich einem Puzzle. Welches ist nicht ideal. Nun, vielleicht wird sich der Wortlaut irgendwann verbessern. Hier ist das CWG-Problem, das ich erwähnt habe, aber es fehlte Platz zum Verknüpfen - open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1701
unsigned charist das Herz aller kleinen Tricks. In fast ALLEN Compilern für ALLE Plattformen unsigned charist ein einfach ein Byte und eine vorzeichenlose Ganzzahl von (normalerweise) 8 Bits, die als kleine Ganzzahl oder als Bitpaket behandelt werden können.
In der Sucht definiert der Standard, wie jemand anderes gesagt hat, nicht das Zeichen eines Zeichens. so haben Sie 3 verschiedene charArten: char, signed char, unsigned char.
Wenn Sie verschiedene Arten von bestimmten Länge und Signedness wie verwendet, sind Sie wahrscheinlich besser dran mit uint8_t, int8_t, uint16_t, etc. , nur weil sie genau das tun , was sie sagen.
Einige Googler fanden dies , wo die Leute darüber diskutierten.
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 möglicherweise Flags aktivieren und deaktivieren, die an eine Funktion übergeben werden sollen, wie dies häufig in der Windows-API der Fall ist).
Ein vorzeichenloses Zeichen verwendet das Bit, das für das Vorzeichen eines regulären Zeichens reserviert ist, als andere Zahl. Dies ändert den Bereich auf [0 - 255] im Gegensatz zu [-128 - 127].
Im Allgemeinen werden vorzeichenlose Zeichen verwendet, wenn Sie kein Zeichen möchten. Dies macht einen Unterschied, wenn Sie beispielsweise Bits verschieben (Shift erweitert das Vorzeichen) und andere Dinge, wenn Sie ein Zeichen als Byte behandeln, anstatt es als Zahl zu verwenden.
zitiert aus dem Buch "The C Programming Laugage":
Das Qualifikationsmerkmal signedoder unsignedkann auf char oder eine beliebige Ganzzahl angewendet werden. vorzeichenlose Zahlen sind immer positiv oder null und folgen den Gesetzen des arithmetischen Modulo 2 ^ n, wobei n die Anzahl der Bits im Typ ist. Wenn Zeichen beispielsweise 8 Bit sind, haben vorzeichenlose Zeichenvariablen Werte zwischen 0 und 255, während vorzeichenbehaftete Zeichen Werte zwischen -128 und 127 haben (in einer Zwei-Komplement-Maschine). Ob einfache Zeichen vorzeichenlos oder vorzeichenlos sind, ist Maschine -abhängige, aber druckbare Zeichen sind immer positiv.
signed charund unsigned charbeide repräsentieren 1 Byte, aber sie haben unterschiedliche Bereiche.
Type | range
-------------------------------
signed char | -128 to +127
unsigned char | 0 to 255
In signed charwenn man bedenkt , char letter = 'A'‚A‘ darstellen, binär von 65 in ASCII/Unicodekann Wenn 65 gespeichert werden , -65 auch gespeichert werden können. Es gibt keine negativen Binärwerte inASCII/Unicode sich keine Gedanken über negative Werte machen müssen.
Beispiel
#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;
}
Ausgabe -:
Signed char(255) : -1
Unsigned char(255) : 255
Signed char(-128) : -128
Unsigned char(-128) : 128