Ist es besser, char oder unsigned char array zum Speichern von Rohdaten zu verwenden?

Lesezeit: 6 Minuten

Benutzeravatar des M310
M310

Wenn einige Rohdaten, beispielsweise aus einem Stream, im Speicher gepuffert werden müssen, ist es besser, ein Array von zu verwenden char Oder von unsigned char? Ich habe immer verwendet char aber bei der Arbeit sagen, es ist besser unsigned char und ich weiß nicht warum.

  • Wenn es sich um einen String-Stream handelt, kann er verwendet werden char Reihe. für andere numerische (z. B. hexadezimale, Bits) Rohdaten ist es am besten, sie zu verwenden unsigned Variablen, damit Sie sich nicht mit dem Vorzeichenbit befassen müssen

    – Iosif Murariu

    12. Juni 2014 um 9:43 Uhr


Benutzeravatar von Tony Delroy
Toni Delroy

UPDATE: C++17 eingeführt std::bytedie besser für “rohe” Datenpuffer geeignet ist als für irgendeine Art von char.

Für frühere C++-Versionen:

  • unsigned char betont, dass die Daten nicht „nur“ Text sind

  • Wenn Sie tatsächlich “Byte” -Daten aus zB einem komprimierten Stream, einer Sicherungsdatei einer Datenbanktabelle, einem ausführbaren Bild, einem JPEG … haben, dann unsigned ist für die oben erwähnte Binärdatenkonnotation geeignet

    • unsigned funktioniert besser für einige der Operationen, die Sie möglicherweise mit Binärdaten durchführen möchten, z. B. gibt es undefinierte und implementierungsdefinierte Verhaltensweisen für einige Bitoperationen bei vorzeichenbehafteten Typen und unsigned Werte können direkt als Indizes in Arrays verwendet werden

    • Sie können nicht versehentlich an übergeben unsigned char* zu einer Funktion erwarten char* und als mutmaßlichen Text operieren lassen

    • In diesen Situationen ist es normalerweise natürlicher, sich die Werte im Bereich von 0 bis 255 vorzustellen – warum sollte das “Vorzeichen” -Bit eine andere Bedeutung haben als die anderen Bits in den Daten?

  • Wenn Sie “Rohdaten” speichern, bei denen es sich auf Anwendungslogik- / Designebene zufällig um numerische 8-Bit-Daten handelt, wählen Sie auf jeden Fall eine der beiden unsigned oder ausdrücklich signed char wie es Ihren Bedürfnissen entspricht

Hinsichtlich der Struktur des Puffers gibt es keinen Unterschied: In beiden Fällen erhalten Sie eine vom Standard vorgeschriebene Elementgröße von einem Byte.

Der vielleicht wichtigste Unterschied, den Sie erhalten, ist das Verhalten, das Sie sehen, wenn Sie auf die einzelnen Elemente des Puffers zugreifen, beispielsweise zum Drucken. Mit char Sie erhalten ein von der Implementierung definiertes Verhalten mit oder ohne Vorzeichen; mit unsigned char Sie sehen immer unsigniertes Verhalten. Dies wird wichtig, wenn Sie die einzelnen Bytes Ihres “Rohdaten”-Puffers drucken möchten.

Eine weitere gute Alternative zur Verwendung für Puffer ist die Ganzzahl mit exakter Breite uint8_t. Es hat garantiert die gleiche Breite wie unsigned charsein Name erfordert weniger Tipparbeit und teilt dem Leser mit, dass Sie die einzelnen Elemente des Puffers nicht als zeichenbasierte Informationen verwenden möchten.

Benutzeravatar von Pablo Francisco Pérez Hidalgo
Pablo Francisco Pérez Hidalgo

Intern ist es genauso: Jedes Element ist ein Byte. Die Differenz ergibt sich, wenn Sie mit diesen Werten arbeiten.

Wenn dein Wertebereich ist [0,255] du solltest benutzen unsigned char aber wenn es so ist [-128,127] dann solltest du verwenden signed char.

Angenommen, Sie verwenden den ersten Bereich (signed char), dann können Sie den Vorgang ausführen 100+100. Andernfalls läuft diese Operation über und gibt Ihnen einen unerwarteten Wert.

Abhängig von Ihrem Compiler- oder Maschinentyp, char kann standardmäßig unsigniert oder signiert sein: Ist char standardmäßig signiert oder unsigniert? So haben char die für die obigen Fälle beschriebenen Bereiche.

Wenn Sie diesen Puffer nur zum Speichern von Binärdaten verwenden, ohne damit zu arbeiten, gibt es keinen Unterschied zwischen der Verwendung char oder unsigned char.

BEARBEITEN

Beachten Sie, dass Sie sogar können ändern Sie die Standardeinstellung char für dieselbe Maschine und denselben Compiler mit Compiler-Flags:

-funsigned-char Lassen Sie den Typ char unsigned sein, wie unsigned char.

Jede Art von Maschine hat einen Standardwert für das, was char sein sollte. Es ist entweder standardmäßig wie unsigned char oder standardmäßig wie signed char. Idealerweise sollte ein portables Programm immer signed char oder unsigned char verwenden, wenn es von der Signiertheit eines Objekts abhängt. Viele Programme wurden jedoch so geschrieben, dass sie einfaches Zeichen verwenden und erwarten, dass es signiert oder nicht signiert ist, je nachdem, für welche Maschinen sie geschrieben wurden. Mit dieser Option und ihrer Umkehrung können Sie ein solches Programm mit der entgegengesetzten Voreinstellung arbeiten lassen.

Der Typ char ist immer ein unterschiedlicher Typ von signed char oder unsigned char, obwohl sein Verhalten immer genau wie eines dieser beiden ist.

  • Sie vermuten char ist unterschrieben. Die Teile “Bereich” und “Überlauf” sind also nicht unbedingt wahr.

    – PP

    12. Juni 2014 um 9:51 Uhr

  • „wenn es ist [-127,127] verwenden char.” char kann auch unsigniert sein, wenn Sie Signiertheit benötigen, verwenden Sie signed char. “… gib dir eine negative Zahl.” Vielleicht, vielleicht auch nicht, ist der vorzeichenbehaftete Überlauf UB.

    – Baum mit Augen

    12. Juni 2014 um 9:53 Uhr


  • @BaummitAugen Es ist wahr, aber in diesem Fall sollte OP nicht erwarten, den gewünschten Wert zu erhalten.

    – Pablo Francisco Pérez Hidalgo

    12. Juni 2014 um 9:56 Uhr

Wie @Pablo in seiner Antwort sagte, ist der Hauptgrund, dass Sie beim Rechnen mit den Bytes die “richtigen” Antworten erhalten, wenn Sie die Bytes als deklarieren unsigned char: Sie möchten (in Pablos Beispiel) 100 + 100 zu 200 addieren; wenn du diese summe mit machst signed char (was Sie versehentlich tun könnten, wenn char auf Ihrem Compiler signiert ist) gibt es keine Garantie dafür – Sie bitten um Ärger.

Ein weiterer wichtiger Grund ist, dass es Ihnen helfen kann, Ihren Code zu dokumentieren, wenn Sie explizit angeben, welche Datentypen was sind. Es ist nützlich zu deklarieren

typedef unsigned char byte

oder noch besser

#include <stdint.h>
typedef uint8_t byte

Verwenden byte danach macht es ein bisschen klarer, was die Absicht Ihres Programms ist. Je nachdem, wie paranoid Ihr Compiler ist (-Wall ist dein Freund), dies könnte sogar eine Typenwarnung verursachen, wenn Sie a geben byte* Argument zu a char* Funktionsargument und fordert Sie auf, etwas genauer darüber nachzudenken, ob Sie das Richtige tun.

Ein ‘Zeichen’ ist grundsätzlich etwas ganz anderes als ein ‘Byte’. C verwischt die Unterscheidung zufällig (weil auf C-Ebene in einer überwiegend ASCII-Welt die Unterscheidung in vielen Fällen keine Rolle spielt). Diese Unschärfe ist nicht immer hilfreich, aber zumindest eine gute intellektuelle Hygiene, um den Unterschied klar im Kopf zu behalten.

Es ist normalerweise besser zu verwenden char aber es macht so wenig Unterschied, dass es keine Rolle spielt. Es handelt sich um Rohdaten, also sollten Sie sie einfach als solche weitergeben, anstatt zu versuchen, damit zu arbeiten char Zeiger der einen oder anderen Art. Seit char der native Datentyp ist, ist es am sinnvollsten, diesen zu verwenden, anstatt sich vorzustellen, dass Sie Ihre Daten in den einen oder anderen Typ zwingen.

Benutzeravatar der Community
Gemeinschaft

Wenn Sie unsigned char verwenden, werden nur gültige ASCII-Zeichen verwendet, da der Bereich -127 bis +127 wird.

und in dieser Frage finden Sie den vollständigen Unterschied zwischen char- und unsigned char-Details.

diff bet char und unsigned char

und Sie können die Tabelle hier sehen.

ASCII-Tabelle

vollständige Tabellen mit Rohzeichen

Benutzeravatar von Anthony
Antonius

Wenn Sie mit C++17 arbeiten können, gibt es einen std::byte-Typ, der besser für die Arbeit mit Rohdaten geeignet ist. Es sind nur bitweise logische Operatoren dafür definiert.

1432660cookie-checkIst es besser, char oder unsigned char array zum Speichern von Rohdaten zu verwenden?

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

Privacy policy