Wofür unsigned char
wird in C / C ++ ein verwendet? Wie unterscheidet es sich von einem normalen char
?
Wofür unsigned char
wird in C / C ++ ein verwendet? Wie unterscheidet es sich von einem normalen char
?
Antworten:
In C ++ gibt es drei verschiedene Zeichentypen:
char
signed char
unsigned char
Wenn 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. sizeof
wäre noch seine Größe berichten wie1
- was bedeutet , dass Sie könnte haben sizeof (char) == sizeof (long) == 1
.
sizeof
da 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 *p
oder 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 signed
oder sein unsigned
, daher müssen Sie explizit nachfragen signed char
oder unsigned char
ob Ihre Implementierung davon abhängt. Verwenden char
Sie 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 char
und unsigned char
ist wie erwartet. Auf den meisten Plattformen signed char
wird eine 8-Bit-Zweierkomplementzahl von reichen-128
bis 127
und unsigned char
eine 8-Bit-Ganzzahl ohne Vorzeichen ( 0
bis 255
). Beachten Sie, dass der Standard NICHT verlangt, dass char
Typen 8 Bit haben, sondern nur diese sizeof(char)
Rückgabe 1
. Sie können die Anzahl der Bits in einem Zeichen mit CHAR_BIT
in ermitteln limits.h
. Es gibt heutzutage nur wenige Plattformen, auf denen dies etwas anderes sein 8
wird.
Es gibt eine schöne Zusammenfassung dieses Problem hier .
Wie andere erwähnt haben , da ich dies geschrieben, du bist besser dran mit int8_t
und uint8_t
wenn Sie wirklich kleine ganze Zahlen darstellen wollen.
CHAR_BIT
Der 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 char
Teilnahme den Wert , wenn jeder unsigned char Objekt zu bestimmen. Zweitens unsigned char
wird 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 konvertieren unsigned char
. Er lehnte die Idee ab, dass das Ergebnis unsigned char
alle 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.3p2
in 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 -1
vor der Konvertierung eins sind. Was haben wir also, damit wir behaupten können, dass das Ergebnis unsigned char
alle seine CHAR_BIT
Bits auf 1 gesetzt hat?
UCHAR_MAX+1
zu-1
erhalten Sie einen Wert im Bereich, nämlichUCHAR_MAX
Das reicht eigentlich! Also, wann immer Sie wollen, unsigned char
dass 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)-1
es eine Art Redewendung ist. ~0
ist nicht.
int x = 1234
und 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 00000000
LSB steht an erster Stelle. Jetzt Hauptteil. wenn ich benutze printf("%d" , *p)
. printf
lesen werden erste Byte ist 11010010
der Ausgang nur , -46
sondern 11010010
ist 210
so , 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 char
wird 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 char
Werte 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 char
ist 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 char
Arithmetik einen Durchschnittswert von (85, 85, 85) . Wenn die Werte jedoch signed char
s (127, -128, -128) wären, würden wir am Ende (-99, -99, -99) haben, was (29, 29, 29) in unserem unsigned char
Raum wäre, was falsch ist .
Wenn Sie ein Zeichen als kleine Ganzzahl verwenden möchten, ist es am sichersten, dies mit den Typen int8_t
und zu tun uint8_t
.
int8_t
und uint8_t
sind optional und nicht auf Architekturen definiert, bei denen die Bytegröße nicht genau 8 Bit beträgt. Umgekehrt signed char
und unsigned char
sind immer verfügbar und halten garantiert mindestens 8 Bit. Es mag ein üblicher Weg sein, aber nicht der sicherste .
signed char
und 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 int
und unsigned int
stattdessen aus irgendeinem Grund?
signed char
und unsigned char
ist 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 char
hat 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 char
ist 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 char
Wert 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_MIN
und CHAR_MAX
während ein vorzeichenloses Zeichen den doppelten Bereich am positiven Ende liefert. Wenn beispielsweise CHAR_BIT
8 ist, char
wird garantiert, dass der reguläre Bereich nur [0, 127] beträgt (da er signiert oder nicht signiert sein kann), während unsigned char
er [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 char
des OP nehmen und dann ++ptr
von 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 char
ist das Herz aller kleinen Tricks. In fast ALLEN Compilern für ALLE Plattformen unsigned char
ist 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 char
Arten: 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 signed
oder unsigned
kann 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 char
und unsigned char
beide repräsentieren 1 Byte, aber sie haben unterschiedliche Bereiche.
Type | range
-------------------------------
signed char | -128 to +127
unsigned char | 0 to 255
In signed char
wenn man bedenkt , char letter = 'A'
‚A‘ darstellen, binär von 65 in ASCII/Unicode
kann 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