uint8_t vs. unsigned char

Lesezeit: 10 Minuten

Umrahmt den Benutzeravatar von Catherine White
Rahmen Catherine White

Was ist der Vorteil der Verwendung uint8_t Über unsigned char in C?

Das kenne ich von fast jedem System uint8_t ist nur eine Typdefinition für unsigned charwarum also verwenden?

Benutzeravatar von Mark Ransom
Mark Lösegeld

Es dokumentiert Ihre Absicht – Sie speichern eher kleine Zahlen als ein Zeichen.

Es sieht auch schöner aus, wenn Sie andere Typedefs verwenden, wie z uint16_t oder int32_t.

  • Explizit verwenden unsigned char oder signed char dokumentiert die Absicht auch, da ungeschminkt char zeigt, dass Sie mit Charakteren arbeiten.

    – Café

    12. November 2009 um 23:37 Uhr

  • Ich dachte, eine schmucklose unsigned war unsigned int per Definition?

    – Markieren Sie Lösegeld

    29. November 2009 um 19:29 Uhr

  • @endolith, die Verwendung von uint8_t für eine Zeichenfolge ist nicht unbedingt falsch, aber definitiv seltsam.

    – Markieren Sie Lösegeld

    14. November 2011 um 13:58 Uhr

  • @endolith, ich denke, ich kann mit UTF8-Text für uint8_t plädieren. In der Tat, char scheint ein Zeichen zu implizieren, während es im Kontext einer UTF8-Zeichenfolge nur ein Byte eines Multibyte-Zeichens sein kann. Die Verwendung von uint8_t könnte deutlich machen, dass man nicht an jeder Position ein Zeichen erwarten sollte – mit anderen Worten, dass jedes Element des Strings/Arrays eine beliebige Ganzzahl ist, über die man keine semantischen Annahmen treffen sollte. Natürlich wissen das alle C-Programmierer, aber es kann Anfänger dazu bringen, die richtigen Fragen zu stellen.

    – tne

    16. Januar 2014 um 11:46 Uhr

  • Ich muss sagen, unsigned char wird nicht wirklich zum Speichern von Zeichen verwendet, daher ist das Problem der “Absicht” strittig.

    – Benutzer541686

    22. Juli 2014 um 11:00 Uhr

Benutzeravatar von Chris Lutz
Chris Lutz

Nur um pedantisch zu sein, einige Systeme haben möglicherweise keinen 8-Bit-Typ. Entsprechend Wikipedia:

Eine Implementierung ist erforderlich, um ganzzahlige Typen mit exakter Breite für N = 8, 16, 32 oder 64 zu definieren, wenn und nur wenn sie einen Typ hat, der die Anforderungen erfüllt. Es ist nicht erforderlich, sie für jedes andere N zu definieren, selbst wenn es die entsprechenden Typen unterstützt.

So uint8_t Es ist nicht garantiert, dass es existiert, obwohl es für alle Plattformen existiert, auf denen 8 Bits = 1 Byte sind. Einige eingebettete Plattformen mögen anders sein, aber das wird sehr selten. Einige Systeme können definieren char 16-Bit-Typen, in diesem Fall wird es wahrscheinlich keinen 8-Bit-Typ geben.

Abgesehen von diesem (kleinen) Problem ist die Antwort von @ Mark Ransom meiner Meinung nach die beste. Verwenden Sie diejenige, die am deutlichsten zeigt, wofür Sie die Daten verwenden.

Außerdem gehe ich davon aus, dass du gemeint hast uint8_t (die Standard-Typedef von C99, die in der stdint.h Kopfzeile) statt uint_8 (nicht Teil einer Norm).

  • @caf, aus reiner Neugier – können Sie auf die Beschreibung einiger verlinken? Ich weiß, dass sie existieren, weil jemand in einer comp.lang.c++.moderierten Diskussion darüber, ob C/C++-Typgarantien zu schwach sind, einen erwähnt (und mit Entwicklerdokumenten dafür verlinkt), aber ich kann diesen Thread nicht mehr finden, und er ist immer praktisch um in ähnlichen Diskussionen darauf hinzuweisen 🙂

    – Pavel Minaev

    12. November 2009 um 23:40 Uhr

  • “Einige Systeme können Zeichentypen mit 16 Bit definieren, in diesem Fall wird es wahrscheinlich keinen 8-Bit-Typ geben.” – und trotz einiger falscher Einwände von mir hat Pavel in seiner Antwort gezeigt, dass, wenn char 16 Bit ist, der Compiler selbst dann einen 8-Bit-Typ bereitstellt darf nicht nennen uint8_t (oder typedef es dazu). Dies liegt daran, dass der 8-Bit-Typ ungenutzte Bits in der Speicherdarstellung hätte, was uint8_t darf nicht haben.

    – Steve Jessop

    13. November 2009 um 3:29 Uhr

  • Die SHARC-Architektur hat 32-Bit-Wörter. Sehen de.wikipedia.org/wiki/… für Details.

    – BCran

    13. November 2009 um 16:17 Uhr

  • Und die C5000-DSPs von TI (die in OMAP1 und OMAP2 enthalten waren) sind 16-Bit. Ich denke, für OMAP3 gingen sie zur C6000-Serie mit einem 8-Bit-Zeichen.

    – Steve Jessop

    13. November 2009 um 17:30 Uhr

  • Graben in N3242 – “Working Draft, Standard for Programming Language C++”, Abschnitt 18.4.1 < cstdint > synopsis sagt – typedef unsigned integer type uint8_t; // optional Im Wesentlichen wird also keine dem C++-Standard entsprechende Bibliothek benötigt, um uint8_t überhaupt zu definieren (siehe Kommentar //optional).

    – nächtliche Wanderwege

    23. Februar 2013 um 9:17 Uhr

AnT steht mit Russlands Benutzer-Avatar
AnT steht zu Russland

Der springende Punkt ist, implementierungsunabhängigen Code zu schreiben. unsigned char ist nicht garantiert ein 8-Bit-Typ. uint8_t ist (falls vorhanden).

  • …wenn es auf einem System existiert, aber das wird sehr selten sein. +1

    – Chris Lutz

    12. November 2009 um 22:57 Uhr

  • Nun, wenn Sie wirklich Probleme damit hatten, dass Ihr Code auf einem System nicht kompiliert wurde, weil uint8_t nicht existierte, könnten Sie find und sed verwenden, um alle Vorkommen von uint8_t automatisch in unsigned char oder etwas Nützlicheres für Sie zu ändern.

    – Buzz

    24. Juli 2014 um 20:36 Uhr

  • @bazz – nicht, wenn Sie davon ausgehen, dass es sich um einen 8-Bit-Typ handelt, den Sie nicht können – zum Beispiel, um Daten zu entpacken, die von einem Remote-System byteweise gepackt wurden. Die implizite Annahme ist, dass der Grund dafür, dass uint8_t nicht vorhanden ist, auf einem Prozessor liegt, auf dem ein Zeichen mehr als 8 Bit lang ist.

    – Chris Stratton

    11. April 2015 um 21:56 Uhr


  • Assertion einwerfen (sizeof(unsigned char) == 8);

    – Buzz

    12. April 2015 um 22:29 Uhr

  • @bazz falsche Behauptung, fürchte ich. sizeof(unsigned char) wird zurückkehren 1 für 1Byte. aber wenn ein System char und int die gleiche Größe von zB 16-Bit haben, dann sizeof(int) wird auch wiederkommen 1

    – Tobi

    29. Mai 2015 um 9:22 Uhr

Benutzeravatar von Justin Love
Nur verliebt

Wie du gesagt hast, “fast jedes System”.

char ist wahrscheinlich einer der weniger wahrscheinlich zu ändern, aber sobald Sie mit der Verwendung beginnen uint16_t und Freunde, mit uint8_t mischt sich besser und kann sogar Teil eines Codierungsstandards sein.

Es gibt wenig. Aus Sicht der Portabilität char kann nicht kleiner als 8 Bit sein, und nichts kann kleiner sein als charwenn also eine bestimmte C-Implementierung einen vorzeichenlosen 8-Bit-Ganzzahltyp hat, wird es so sein char. Alternativ kann es sein, dass es gar keins hat, an welchem ​​Punkt eines typedef Tricks sind umstritten.

Es könnte verwendet werden, um Ihren Code in dem Sinne besser zu dokumentieren, dass klar ist, dass Sie dort 8-Bit-Bytes benötigen und sonst nichts. Aber in der Praxis ist es praktisch überall schon eine vernünftige Erwartung (es gibt DSP-Plattformen, auf denen es nicht zutrifft, aber die Chancen, dass Ihr Code dort läuft, sind gering, und Sie könnten genauso gut einen Fehler machen, indem Sie eine statische Bestätigung oben in Ihrem Programm verwenden eine solche Plattform).

  • Fürs Protokoll: Sie könnten auf jeder Plattform einen 8-Bit-Typ erstellen: typedef struct { unsigned i :8; } uint8_t; aber Sie müssten es als verwenden uint8_t x; x.i = ... also etwas umständlicher.

    – Chris Lutz

    12. November 2009 um 22:45 Uhr

  • @Skizz – Nein, der Standard erfordert unsigned char Werte zwischen 0 und 255 halten zu können. Wenn du das in 4 Bit schaffst, dann ziehe ich den Hut.

    – Chris Lutz

    12. November 2009 um 22:50 Uhr

  • “es wäre ein bisschen umständlicher” – umständlich in dem Sinne, dass Sie den ganzen Weg dorthin laufen (schwimmen, ein Flugzeug nehmen usw.) müssten, wo der Compiler-Autor war, und ihm auf den Hinterkopf schlagen , und lassen Sie sie hinzufügen uint8_t zur Umsetzung. Ich frage mich, ob Compiler für DSPs normalerweise 16-Bit-Zeichen implementieren uint8_toder nicht?

    – Steve Jessop

    12. November 2009 um 23:06 Uhr

  • Übrigens, bei näherer Überlegung ist es vielleicht die einfachste Art zu sagen “Ich brauche wirklich 8 Bit” – #include <stdint.h>und verwenden uint8_t. Wenn die Plattform es hat, wird es Ihnen gegeben. Wenn die Plattform es nicht hat, wird Ihr Programm nicht kompiliert, und der Grund wird klar und einfach sein.

    – Pavel Minaev

    12. November 2009 um 23:23 Uhr

  • Immer noch keine Zigarre, sorry: “Für unsigned Integer-Typen außer unsigned char müssen die Bits der Objektdarstellung in zwei Gruppen unterteilt werden: Wertbits und Füllbits … Wenn es N Wertbits gibt, soll jedes Bit ein anderes darstellen Potenz von 2 zwischen 1 und 2^(N-1), sodass Objekte dieses Typs in der Lage sein sollen, Werte von 0 bis 2^(N-1) unter Verwendung einer reinen binären Darstellung darzustellen … Der Typedef-Name intN_t bezeichnet a vorzeichenbehafteter ganzzahliger Typ mit Breite N, keine Füllbitsund eine Zweierkomplementdarstellung.”

    – Pavel Minaev

    13. November 2009 um 2:38 Uhr

Benutzeravatar der Community
Gemeinschaft

Meiner Erfahrung nach gibt es zwei Stellen, an denen wir uint8_t verwenden möchten, um 8 Bit (und uint16_t usw.) zu bedeuten, und an denen wir Felder haben können, die kleiner als 8 Bit sind. An beiden Stellen kommt es auf Platz an, und wir müssen uns beim Debuggen oft einen Rohdatenauszug der Daten ansehen und schnell feststellen können, was er darstellt.

Der erste liegt in HF-Protokollen, insbesondere in Schmalbandsystemen. In dieser Umgebung müssen wir möglicherweise so viele Informationen wie möglich in eine einzige Nachricht packen. Der zweite ist der Flash-Speicher, wo wir möglicherweise sehr begrenzten Platz haben (z. B. in eingebetteten Systemen). In beiden Fällen können wir eine gepackte Datenstruktur verwenden, bei der der Compiler das Packen und Entpacken für uns übernimmt:

#pragma pack(1)
typedef struct {
  uint8_t    flag1:1;
  uint8_t    flag2:1;
  padding1   reserved:6;  /* not necessary but makes this struct more readable */
  uint32_t   sequence_no;
  uint8_t    data[8];
  uint32_t   crc32;
} s_mypacket __attribute__((packed));
#pragma pack()

Welche Methode Sie verwenden, hängt von Ihrem Compiler ab. Möglicherweise müssen Sie auch mehrere verschiedene Compiler mit denselben Header-Dateien unterstützen. Dies geschieht in eingebetteten Systemen, in denen Geräte und Server völlig unterschiedlich sein können – beispielsweise haben Sie möglicherweise ein ARM-Gerät, das mit einem x86-Linux-Server kommuniziert.

Es gibt ein paar Vorbehalte bei der Verwendung von gepackten Strukturen. Das größte Problem ist, dass Sie vermeiden müssen, die Adresse eines Mitglieds zu dereferenzieren. Auf Systemen mit Multibyte-ausgerichteten Wörtern kann dies zu einer falsch ausgerichteten Ausnahme und einem Arbeitsspeicherabzug führen.

Einige Leute werden sich auch Sorgen um die Leistung machen und argumentieren, dass die Verwendung dieser gepackten Strukturen Ihr System verlangsamen wird. Es stimmt, dass der Compiler hinter den Kulissen Code hinzufügt, um auf die nicht ausgerichteten Datenelemente zuzugreifen. Sie können das sehen, indem Sie sich den Assembler-Code in Ihrer IDE ansehen.

Aber da gepackte Strukturen für die Kommunikation und Datenspeicherung am nützlichsten sind, können die Daten in eine nicht gepackte Darstellung extrahiert werden, wenn man damit im Speicher arbeitet. Normalerweise müssen wir sowieso nicht mit dem gesamten Datenpaket im Speicher arbeiten.

Hier ist eine relevante Diskussion:

pragma pack(1) noch __attribute__ ((aligned (1))) funktioniert

Ist das __attribute__((packed))/#pragma pack von gcc unsicher?

http://solidsmoke.blogspot.ca/2010/07/woes-of-structure-packing-pragma-pack.html

  • Fürs Protokoll: Sie könnten auf jeder Plattform einen 8-Bit-Typ erstellen: typedef struct { unsigned i :8; } uint8_t; aber Sie müssten es als verwenden uint8_t x; x.i = ... also etwas umständlicher.

    – Chris Lutz

    12. November 2009 um 22:45 Uhr

  • @Skizz – Nein, der Standard erfordert unsigned char Werte zwischen 0 und 255 halten zu können. Wenn du das in 4 Bit schaffst, dann ziehe ich den Hut.

    – Chris Lutz

    12. November 2009 um 22:50 Uhr

  • “es wäre ein bisschen umständlicher” – umständlich in dem Sinne, dass Sie den ganzen Weg dorthin laufen (schwimmen, ein Flugzeug nehmen usw.) müssten, wo der Compiler-Autor war, und ihm auf den Hinterkopf schlagen , und lassen Sie sie hinzufügen uint8_t zur Umsetzung. Ich frage mich, ob Compiler für DSPs normalerweise 16-Bit-Zeichen implementieren uint8_toder nicht?

    – Steve Jessop

    12. November 2009 um 23:06 Uhr

  • Übrigens, bei näherer Überlegung ist es vielleicht die einfachste Art zu sagen “Ich brauche wirklich 8 Bit” – #include <stdint.h>und verwenden uint8_t. Wenn die Plattform es hat, wird es Ihnen gegeben. Wenn die Plattform es nicht hat, wird Ihr Programm nicht kompiliert, und der Grund wird klar und einfach sein.

    – Pavel Minaev

    12. November 2009 um 23:23 Uhr

  • Immer noch keine Zigarre, sorry: “Für unsigned Integer-Typen außer unsigned char müssen die Bits der Objektdarstellung in zwei Gruppen unterteilt werden: Wertbits und Füllbits … Wenn es N Wertbits gibt, soll jedes Bit ein anderes darstellen Potenz von 2 zwischen 1 und 2^(N-1), sodass Objekte dieses Typs in der Lage sein sollen, Werte von 0 bis 2^(N-1) unter Verwendung einer reinen binären Darstellung darzustellen … Der Typedef-Name intN_t bezeichnet a vorzeichenbehafteter ganzzahliger Typ mit Breite N, keine Füllbitsund eine Zweierkomplementdarstellung.”

    – Pavel Minaev

    13. November 2009 um 2:38 Uhr

Benutzeravatar von VP
VP.

Das ist zum Beispiel wirklich wichtig, wenn Sie einen Netzwerkanalysator schreiben. Paket-Header werden durch die Protokollspezifikation definiert, nicht durch die Funktionsweise des C-Compilers einer bestimmten Plattform.

  • Damals, als ich das fragte, war ich definitiv ein einfaches Protokoll für die Kommunikation über die serielle Schnittstelle.

    – Frames Catherine White

    4. Juni 2011 um 11:47 Uhr

1426570cookie-checkuint8_t vs. unsigned char

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

Privacy policy