Frage

Wenn ein Puffer von Bytes char oder unsigned char oder einfach einen char buffer unterzeichnet werden? Unterschiede zwischen C und C ++?

Danke.

War es hilfreich?

Lösung

  

Wenn ein Puffer von Bytes zu unterzeichnen   char oder unsigned char oder einfach ein char   Puffer, Prellbock, Dämpfer? Unterschiede zwischen C und   C ++?

Ein kleiner Unterschied, wie die Sprache, es behandelt. Ein großen Unterschied, wie Konvention behandelt es.

  • char = ASCII (oder UTF-8, aber die Signedness in die Quere kommt es) Text Daten
  • unsigned char = Byte
  • signed char = selten verwendet

Und es ist Code, der setzt auf eine solche Unterscheidung. Nur eine Woche oder zwei Jahren traf ich einen Fehler in dem JPEG-Daten wurden beschädigt zu werden, da es wurde auf die char* Version unserer Base64 kodieren Funktion übergeben werden - die „helfend“ alle ungültigen UTF-8 ersetzt in der „string“. Ändern aka BYTE unsigned char war alles, es dauerte es zu beheben.

Andere Tipps

Wenn Sie beabsichtigen, beliebige binäre Daten zu speichern, sollten Sie unsigned char verwenden. Es ist der einzige Datentyp, der keine Füllbits von C-Standard haben, gewährleistet ist. Jeder anderer Datentyp kann Füllbits in ihrer Objektdarstellung enthält (das ist derjenige, der alle Bits eines Objekts enthält, und nicht nur diejenigen, die einen Wert bestimmt). Die Füllbits Zustand ist nicht näher bezeichnet sind und nicht zum Speichern von Werten verwendet. Also, wenn Sie einige binäre Daten mit char lesen, würde die Dinge geschnitten werden bis auf den Wertebereich eines char (indem nur die Wert-Bits zu interpretieren), aber es gibt noch Bits sein kann, die einfach ignoriert werden, aber immer noch da sind und von memcpy lesen. Ähnlich wie Füllbits in Echt struct Objekte. Typ unsigned char garantiert diejenigen, die nicht enthalten. Das ergibt sich aus 5.2.4.2.1/2 (C99 TC2, n1124 hier):

  

Wenn der Wert von einem Objekt vom Typ char wird als vorzeichenbehaftete ganze Zahl behandelt, wenn sie in einem verwendet   Ausdruck wird der Wert von CHAR_MIN das gleiche sein wie die des SCHAR_MIN und dem   Wert von CHAR_MAX ist das gleiche wie die von SCHAR_MAX sein. Andernfalls wird der Wert von   CHAR_MIN soll 0 sein und der Wert von CHAR_MAX soll das gleiche sein wie die der   UCHAR_MAX. Der Wert UCHAR_MAX wird gleich 2^CHAR_BIT − 1

Aus dem letzten Satz folgt, dass es keinen Raum für irgendwelche Paddingbits links ist. Wenn Sie char als Typ Ihres Puffer zu verwenden, müssen Sie auch das Problem der Überläufe: einen beliebigen Wert zuweisen explizit auf ein solches Element, das im Bereich von 8 Bits ist - so können Sie eine solche Zuordnung erwarten in Ordnung zu sein - aber nicht innerhalb der Bereich eines char, die CHAR_MIN..CHAR_MAX, eine solche Umwandlung überläuft und bewirkt, dass die Umsetzung definiert Ergebnisse, einschließlich der Erhöhung von Signalen.

ist

Auch wenn irgendwelche Probleme der oben in Bezug auf würden wahrscheinlich in realen Implementierungen zeigen nicht (wäre ein sehr schlechte Qualität der Implementierung), Sie sind am besten die richtige Art von Anfang an ab, verwenden, das ist unsigned char.

Bei Strings der Datentyp der Wahl ist jedoch char, die durch Streich- und Druckfunktionen verstanden wird. Mit signed char für diese Zwecke sieht aus wie eine falsche Entscheidung für mich.

Für weitere Informationen lesen Sie this proposal die enthalten ein Update für eine nächste Version des C-Standard, die schließlich erfordern signed char keine Füllbits haben entweder. Es ist bereits in die rel="noreferrer">.

Es hängt davon ab.

Wenn der Puffer Text halten soll, dann ist es wahrscheinlich sinnvoll, es als ein Array von char zu erklären, und lassen Sie die Plattform für Sie entscheiden, ob die Unterzeichnung oder standardmäßig nicht signiert. Das gibt Ihnen die geringste Mühe Führen der Daten in die und aus der Laufzeitbibliothek Implementierung, zum Beispiel.

Wenn der Puffer soll binäre Daten halten, dann hängt es davon ab, wie Sie beabsichtigen, es zu benutzen. Wenn beispielsweise die binären Daten wirklich eine gepackte Anordnung von Datenproben, die 8-Bit-Festpunkt ADC Messungen unterzeichnet werden, dann wäre signed char am besten.

In den meisten realen Fällen ist der Puffer nur, dass ein Puffer, und Sie nicht wirklich über die Art des einzelnen Bytes, weil Sie den Puffer in einem Massenvorgang gefüllt, und Sie sind dabei, es zu passieren aus, um einen Parser die komplexe Datenstruktur und etwas Sinnvolles tun zu interpretieren. In diesem Fall meldet es auf einfachste Art und Weise.

Wenn es tatsächlich ein Puffer von 8-Bit-Bytes, anstatt eine Zeichenfolge in dem Standardgebietsschema der Maschine, dann würde ich uint8_t verwenden. Nicht, dass es viele Maschinen um, wo ein Zeichen ist kein Byte (oder ein Byte ein Oktett), aber macht die Aussage ‚das ist ein Puffer von Bytes‘ und nicht ‚dies ist ein String‘ wird oft nützliche Dokumentation.

Sie sollten entweder char oder unsigned char und nie signed char . Der Standard hat folgende in 3,9 / 2

  

Für jedes Objekt (andere als ein   Basisklasse Subobjekt) des POD-Typ T,   ob oder nicht hält das Objekt ein   gültige Wert vom Typ T, die darunter liegenden   Bytes (1.7) kann das Objekt bilden,   kopiert werden, in eine Anordnung von char oder   unsigned char.If der Gehalt an   das Array von char oder unsigned char ist   zurück in das Objekt kopiert, die   Objekt wird anschließend halten ihre   ursprünglicher Wert.

Es ist besser, es als unsigned char zu definieren. Infact Win32 Typ Byte als unsigned char definiert. Es gibt keinen Unterschied zwischen C & C ++ zwischen diesen.

Für maximale Portabilität verwenden immer unsigned char. Es gibt ein paar Fälle, in denen dies ins Spiel kommen könnte. Serialisierten Daten zwischen Systemen mit unterschiedlichen Endian-Typ geteilt kommt sofort in den Sinn. Beim Durchführen Verschiebung oder Bit der Werte Maskieren ist eine andere.

Die Wahl der int8_t vs uint8_t ist ähnlich, wenn Sie eine ptr sein NULL vergleichen.


Von einer Funktionalität Sicht auf NULL zu vergleichen ist das gleiche wie im Vergleich zu 0, weil NULL ein #define für 0 ist.

Aber persönlich von einem Codierungsstil Sicht, wähle ich meine Zeiger auf NULL zu vergleichen, weil die NULL #define an der Person konnotiert den Code beibehalten, die Sie für einen schlechten Zeiger werden überprüft ...

VS

, wenn jemand einen Vergleich zu 0 sieht es konnotiert, dass Sie für einen bestimmten Wert prüft wird.


Aus dem obigen Grunde würde ich verwenden uint8_t.

Wenn Sie ein Element in einen größeren Variable holen, wird es natürlich sein vorzeichenerweiterte oder nicht.

sollte und ... Ich neige dazu, bevorzugen nicht unterzeichnet, da es fühlt sich mehr „raw“, weniger einladend zu sagen: „Hey, das ist nur ein Haufen von kleinen ints“, wenn ich will betont die binär-ness der Daten.

Ich glaube nicht, dass ich jemals eine explizite signed char einen Puffer von Bytes darstellen verwendet.

Natürlich ist eine dritte Möglichkeit ist, den Puffer als void * so viel wie möglich zu vertreten. Viele gängige E / A-Funktionen arbeiten mit void *, so dass manchmal die Entscheidung, was Integer-Typ kann verwendet werden vollständig gekapselt werden, was schön ist.

Vor einigen Jahren hatte ich ein Problem mit einer C ++ Konsolenanwendung, die farbigen Zeichen für ASCII-Werte über 128 gedruckt und wurde dieses Problem gelöst, indem von char unsigned char wechseln, aber ich denke, es lösbar gewesen war, während char-Typen zu halten, auch.

Für jetzt, die meisten C / C ++ Funktionen char und ich verstehe beiden Sprachen jetzt viel besser, so dass ich char in den meisten Fällen.

Kümmern Sie wirklich? Wenn Sie dies nicht tun, verwenden Sie einfach den Standard (char) und keine Unordnung Ihren Code nicht mit unwichtiger Angelegenheit. Andernfalls wird künftig Maintainer sich fragen, warum verlassen Sie (oder ohne Vorzeichen), verwenden Sie unterzeichnet haben. Machen Sie ihr Leben einfacher.

Wenn Sie an den Compiler liegen, wird es Sie bestrafen.

Wenn der Puffer enthält Daten, die gerade durchlaufen, und Sie werden sie nicht in irgendeiner Weise manipulieren, spielt es keine Rolle.

Wenn Sie jedoch auf den Pufferinhalt arbeiten müssen dann die richtige Typdeklaration wird Ihr Code einfacher. No "int val = buf [i] & 0xff;" Unsinn.

Also, darüber nachzudenken, was die Daten tatsächlich ist und wie Sie es verwenden müssen.

typedef char byte;

Jetzt können Sie Ihr Array machen von bytes sein. Es ist für jeden offensichtlich, was Sie meinen, und Sie verlieren keine Funktionalität.

Ich weiß, dass es etwas albern, aber es macht den Code lesen 100%, wie Sie beabsichtigten.

scroll top