Sollte ein Puffer von Bytes signierter oder unsignierter Char-Puffer sein?

Lesezeit: 6 Minuten

Sollte ein Puffer von Bytes ein Zeichen mit Vorzeichen oder ein Zeichen ohne Vorzeichen oder einfach ein Zeichenpuffer sein? Irgendwelche Unterschiede zwischen C und C++?

Vielen Dank.

  • Dupe mit stackoverflow.com/questions/13819820

    – Kebs

    24. Januar 2018 um 15:18 Uhr

Johannes Schaub - Benutzerbild der litb
Johannes Schaub – litb

Wenn Sie beabsichtigen, beliebige Binärdaten zu speichern, sollten Sie verwenden unsigned char. Es ist der einzige Datentyp, der vom C-Standard garantiert keine Füllbits enthält. Jeder andere Datentyp kann Füllbits in seiner Objektdarstellung enthalten (also diejenige, die alle Bits eines Objekts enthält, anstatt nur die, die einen Wert bestimmen). Der Zustand der Füllbits ist nicht spezifiziert und wird nicht zum Speichern von Werten verwendet. Also, wenn Sie mit lesen char Bei einigen Binärdaten würden die Dinge auf den Wertebereich eines Zeichens reduziert (indem nur die Wertbits interpretiert werden), aber es kann immer noch Bits geben, die einfach ignoriert werden, aber dennoch vorhanden sind und gelesen werden memcpy. Ähnlich wie Füllbits in echten Strukturobjekten. Typ unsigned char enthält diese garantiert nicht. Das folgt aus 5.2.4.2.1/2 (C99 TC2, n1124 hier):

Wenn der Wert eines Objekts vom Typ char bei Verwendung in einem Ausdruck als Ganzzahl mit Vorzeichen behandelt wird, wird der Wert von CHAR_MIN soll die gleiche sein wie die von SCHAR_MIN und der Wert von CHAR_MAX soll die gleiche sein wie die von SCHAR_MAX. Andernfalls ist der Wert von
CHAR_MIN soll 0 und der Wert von sein CHAR_MAX soll die gleiche sein wie die von
UCHAR_MAX. Der Wert UCHAR_MAX soll gleich sein 2^CHAR_BIT − 1

Aus dem letzten Satz folgt, dass kein Platz mehr für Füllbits bleibt. Wenn du benutzt char Als Typ Ihres Puffers haben Sie auch das Problem von Überläufen: Weisen Sie einem solchen Element, das im Bereich von liegt, einen beliebigen Wert explizit zu 8 Bits – Sie können also davon ausgehen, dass eine solche Zuordnung in Ordnung ist – aber nicht im Bereich von a charwelches ist CHAR_MIN..CHAR_MAXso läuft eine solche Konvertierung über und verursacht implementierungsdefinierte Ergebnisse, einschließlich der Signalerhöhung.

Auch wenn Probleme in Bezug auf das oben Gesagte wahrscheinlich nicht in realen Implementierungen auftreten würden (wäre a sehr schlechte Qualität der Implementierung), verwenden Sie am besten von Anfang an den richtigen Typ, nämlich unsigned char.

Für Strings ist jedoch der Datentyp der Wahl char, die von String- und Druckfunktionen verstanden wird. Verwenden signed char für diese Zwecke sieht für mich nach einer Fehlentscheidung aus.

Weitere Informationen finden Sie unter this proposal die einen Fix für eine nächste Version des C-Standards enthalten, die eventuell benötigt wird signed char haben auch keine Füllbits. Es ist bereits in die integriert Arbeitspapier.

  • B-aber C99 6.2.6.2 sagt “signed char darf keine Füllbits haben”

    – StaceyGirl

    17. Januar 2014 um 1:16 Uhr

  • Vergiss C. [C++11: 3.9.1/1]: [..] Ein Zeichen, ein Zeichen mit Vorzeichen und ein Zeichen ohne Vorzeichen belegen die gleiche Menge an Speicherplatz und haben die gleichen Ausrichtungsanforderungen (3.11); das heißt, sie haben dieselbe Objektdarstellung. Bei Zeichentypen nehmen alle Bits der Objektdarstellung an der Wertdarstellung teil. [..] Deutet das nicht darauf hin alle drei Charaktertypen haben zumindest die gleich Polsterung? Und ich interpretiere es weiter so, dass keiner von ihnen welche hat.

    – Leichtigkeitsrennen im Orbit

    17. Januar 2014 um 1:32 Uhr

  • uintN_t und intN_t haben auch keine Füllbytes.

    – 12431234123412341234123

    25. April 2017 um 7:37 Uhr

Sollte ein Puffer von Bytes ein Zeichen mit Vorzeichen oder ein Zeichen ohne Vorzeichen oder einfach ein Zeichenpuffer sein? Irgendwelche Unterschiede zwischen C und C++?

Ein kleiner Unterschied, wie die Sprache damit umgeht. EIN riesig Unterschied, wie die Konvention damit umgeht.

  • char = ASCII (oder UTF-8, aber die Vorzeichen stehen dort im Weg) textlich Daten
  • unsigned char = Byte
  • signed char = selten verwendet

Und es gibt Code dafür beruht auf eine solche Unterscheidung. Erst vor ein oder zwei Wochen stieß ich auf einen Fehler, bei dem JPEG-Daten beschädigt wurden, weil sie an die weitergegeben wurden char* Version unserer Base64-Kodierungsfunktion – die „hilfreich“ alle ungültigen UTF-8 in der „Zeichenfolge“ ersetzte. Wechseln zu BYTE auch bekannt unsigned char war alles, was es brauchte, um es zu reparieren.

  • Warum also verwenden die C++-Iostreams char* Anstatt von unsigned char* zur Darstellung von Datenpuffern beim Lesen und Schreiben von Binärströmen read und write Methoden? 😛

    – BarbaraKwarc

    13. Januar 2017 um 11:06 Uhr

  • signed char ist gar nicht so selten. In JNI (java native interface, NDK 14.1) ist signed char als jbyte definiert.

    – r0n9

    7. April 2017 um 0:45 Uhr

  • wtf hat java damit zu tun (ugh)

    – Entwicklerbmw

    17. September 2017 um 8:05 Uhr

  • @developerbmw: Herr Gosling [inventor of Java] sah all die Schwierigkeiten, die durch vorzeichenlose Typen verursacht wurden, die nicht zu einem vorzeichenbehafteten Integer-Typ befördert wurden, und entschied daher, dass Java dies nicht tun sollte irgendein unsignierte Typen (außer – aus irgendeinem Grund –char), anstatt zu sagen – wie es einige andere Sprachen wie Pascal getan hatten – dass die einzigen vorzeichenlosen Typen diejenigen sein sollten, die zu einem vorzeichenbehafteten Integer-Typ werden würden.

    – Superkatze

    13. Juli 2018 um 16:00 Uhr


Es hängt davon ab, ob.

Wenn der Puffer Text enthalten soll, ist es wahrscheinlich sinnvoll, ihn als Array von zu deklarieren char und lassen Sie die Plattform für Sie entscheiden, ob dies standardmäßig signiert oder unsigniert ist. Dadurch haben Sie beispielsweise die geringsten Probleme, die Daten in die und aus der Laufzeitbibliothek der Implementierung zu übergeben.

Wenn der Puffer Binärdaten enthalten soll, hängt dies davon ab, wie Sie ihn verwenden möchten. Wenn zum Beispiel die Binärdaten wirklich ein gepacktes Array von Datenabtastwerten sind, die 8-Bit-Festkomma-ADC-Messungen sind, dann signed char wäre am besten.

In den meisten realen Fällen ist der Puffer genau das, ein Puffer, und Sie kümmern sich nicht wirklich um die Typen der einzelnen Bytes, weil Sie den Puffer in einer Massenoperation gefüllt haben und ihn gleich an a übergeben möchten Parser, um die komplexe Datenstruktur zu interpretieren und etwas Nützliches zu tun. Deklarieren Sie es in diesem Fall auf einfachste Weise.

Wenn es sich tatsächlich um einen Puffer mit 8-Bit-Bytes handelt und nicht um eine Zeichenfolge im Standardgebietsschema des Computers, würde ich verwenden uint8_t. Nicht, dass es viele Maschinen gibt, auf denen ein Zeichen kein Byte (oder ein Byte ein Oktett) ist, aber die Aussage „Dies ist ein Puffer von Oktetten“ anstelle von „Dies ist eine Zeichenfolge“ ist oft eine nützliche Dokumentation.

Sie sollten beides verwenden verkohlen oder unsigned char aber nie unterschriebenes Zeichen. Der Standard hat folgendes in 3.9/2

Für jedes Objekt (außer einem Unterobjekt der Basisklasse) des POD-Typs T, unabhängig davon, ob das Objekt einen gültigen Wert des Typs T enthält oder nicht, können die zugrunde liegenden Bytes (1.7), aus denen das Objekt besteht, in ein Array von char oder unsigned kopiert werden char. Wenn der Inhalt des Arrays von char oder unsigned char zurück in das Objekt kopiert wird, soll das Objekt anschließend seinen ursprünglichen Wert behalten.

Benutzeravatar von Naveen
Naveen

Es ist besser, es als unsigned char zu definieren. Tatsächlich ist der Win32-Typ BYTE als unsigned char definiert. Es gibt keinen Unterschied zwischen C und C++.

Benutzeravatar von MrEvil
MrEvil

Verwenden Sie für maximale Portabilität immer unsigned char. Es gibt ein paar Fälle, in denen dies ins Spiel kommen könnte. Serialisierte Daten, die über Systeme mit unterschiedlichem Endian-Typ geteilt werden, fallen sofort ein. Beim Durchführen von Verschiebung oder Bitmaskierung sind die Werte andere.

1413960cookie-checkSollte ein Puffer von Bytes signierter oder unsignierter Char-Puffer sein?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy