Gibt es einen Grund, nicht zu verwenden, die Feste Breite integer-Typen (z.B. uint8_t)?
Vorausgesetzt, Sie verwenden einen compiler, der C99 unterstützt (oder auch nur stdint.h), gibt es einen Grund, nicht zu verwenden, die Feste Breite integer-Typen wie uint8_t?
Einen Grund, dass ich bewusst bin, ist, dass es macht viel mehr Sinn char
s beim Umgang mit Zeichen statt mit (u)int8_t
s, wie erwähnt, in diese Frage.
Aber wenn Sie planen, das speichern einer Nummer, wenn Sie möchten, verwenden Sie eine Art, dass Sie nicht wissen, wie groß es ist? I. e. In welcher situation würden Sie wollen, um eine Nummer zu speichern in einer unsigned short
ohne zu wissen, ob es 8, 16 oder sogar 32 bit, statt mit einem uint16t
?
Anschluss an diese, wird es als eine bessere Praxis zu verwenden, die Feste Breite Integer-zahlen, oder verwenden Sie die normale integer-Typen und nur nie ausgehen und verwenden Sie sizeof
wo Sie brauchen, um zu wissen, wie viele bytes Sie verwenden?
- mögliche Duplikate von Gründe für die Verwendung (oder nicht) stdint
- Siehe auch diese Frage Exotische Architekturen der standard committee kümmert sich um
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ist es eigentlich durchaus üblich, um eine Nummer zu speichern, ohne zu wissen, die genaue Größe des Typs. Es gibt viele Mengen, die in meinen Programmen, dass ich davon ausgehen nicht mehr als 2 Milliarden, oder erzwingen Sie nicht. Aber das bedeutet nicht, brauche ich eine exakte 32-bit-Typ zu speichern, jeglicher Art, die zählen können, auf mindestens 2 Milliarden ist für mich in Ordnung.
Werden, wenn Sie versuchen zu schreiben, sehr portabler code, müssen Sie Bedenken, dass die fixed-width Datentypen werden alle optional.
Auf einen C99-Implementierung, in denen
CHAR_BIT
größer ist als8
es gibt keineint8_t
. Der standard verbietet es existiert, weil es müsste padding-bits, undintN_t
Typen definiert sind, haben keine Polsterung-bits (7.18.1.1/1).uint8_t
daher auch verboten, weil (auch Dank ouah), eine Umsetzung ist nicht erlaubt, zu definierenuint8_t
ohneint8_t
.So, in sehr portabler code, wenn Sie eine signierte Art halten können Werte bis zu 127 dann sollten Sie mit einer
signed char
,int
,int_least8_t
oderint_fast8_t
je nachdem, ob Sie möchten, bitten Sie den compiler, um ihn:signed char
oderint
)int
)int_least8_t
odersigned char
)int_fast8_t
oderint
)Das gleiche gilt für einen vorzeichenlosen Typ bis 255, mit
unsigned char
,unsigned int
,uint_least8_t
unduint_fast8_t
.Wenn Sie brauchen, modulo-256-Arithmetik in sehr portabler code, dann kann man entweder das Modul selbst, bits maskieren, oder spielen mit bitfields.
In der Praxis, die meisten Leute werden nie brauchen, um code zu schreiben, der portabel ist. Im moment
CHAR_BIT > 8
kommt nur auf Spezial-hardware, und Ihr general-purpose-code nicht erhalten, es verwendet. Natürlich, das könnte sich in Zukunft ändern, aber wenn es nicht, ich vermute, dass es so viel code macht Annahmen über die Posix-und/oder Windows (beides gewährleistetCHAR_BIT == 8
), dass der Umgang mit dem code nicht-übertragbarkeit wird ein kleiner Teil einer großen Anstrengung, um den port-code auf die neue Plattform. Jede solche Realisierung ist wahrscheinlich gehen zu müssen, Gedanken machen, wie Sie mit dem internet verbinden (die sich in Octets (Oktette eingehend), lange bevor Sie sich sorgen, wie man Ihren code laufen 🙂Wenn Sie unter der Annahme, dass
CHAR_BIT == 8
sowieso dann ich glaube nicht, dass es irgendeinen bestimmten Grund, um zu vermeiden(u)int8_t
andere, als wenn Sie möchten, dass der code funktioniert in C89. Auch in C89 es ist nicht so schwierig zu finden und schreiben Sie eine version vonstdint.h
für eine bestimmte Implementierung. Aber wenn man leicht schreiben Sie Ihren code zu erfordern nur, dass der Typ255
, anstatt zu verlangen, dass es nicht halten256
, dann könnten Sie auch vermeiden, die Abhängigkeit vonCHAR_BIT == 8
.intN_t
eher alsuintN_t
. Aber der Absatz, der besagt, dass, wenn es eine Typ mit den richtigen Eigenschaften, dannuintN_t
definiert werden muss, sagt, dass es nur die erforderlich zu existieren, wenn es einen 8-bit-unsigned-Typ keine Polsterung (die gibt es nicht). Also, was ich sagte, dass es etwas falsch ist, denke ich, dass, wennCHAR_BIT > 8
dannint8_t
ist verboten aberuint8_t
ist immer noch optional.uint8_t
definiert ist, dannint8_t
erforderlich ist, werden auch die gemäß C99, 7.18.1p1.uint8_t
existieren, wenn die Umsetzung nicht über eine 8-bit integer ? (wenn es erforderlich ist, um genau 8 bits)uint8_t
ist ein 8-bit-integer, so dass, wenn es existiert, dann ist die Umsetzung liefert ein 8-bit-integer. Sorry für jede Verwirrung, die ich verursacht durch die änderung meiner Geschichte, wenn es gestattet ist, zu existieren. Umgekehrt, wird eine Implementierung mitCHAR_BIT > 8
könnte eine 8-bit-Ganzzahl, als eine erweiterte Form, es ist nicht nur nicht erlaubt, es zu nennenuint8_t
.CHAR_BIT
ist die Nummer des bits für das kleinste Objekt, dass nicht ein bit-Feld, so bedeutet dies, dass es ein bit-Feld, um es zu implementieren ? oder ist es erlaubt, von der Norm zu definieren, die eine erweiterte Form, die kleiner ist alsCHAR_BIT
?int
ist nur garantiert durch die Norm von mindestens 32 bits, so dass Sie nicht verwenden können, es zuverlässig. Und das ist schlimmer als fehlende exakte Breite Typen, weil der code kompiliert wird, sondern zur Laufzeit scheitern.int
ist nur garantiert werden, der mindestens 16 bits, die durch den C-standard.long
ist mindestens 32. Aber ich verstehe nicht, was ist der Punkt, den du machst. Wenn ich eine Menge, die nicht mehr als 2 Milliarden, und eine signierte Art garantiert mindestens 32 bits, dann habe ich kann verwenden Sie zuverlässig. Solange ich es nicht mache bitweise Operationen (und manchmal sogar dann), es bleibt richtig, ob es genau 32 oder größer.int
garantiert werden mindestens 16 bits, also kann es nicht verwendet werden, zuverlässig, für Mengen über 32767, und zur Aufbewahrung von 2 Milliarden inint
überlaufen konnten auf einigen Plattformen.Einem Problem, das bisher noch nicht erwähnt wurde ist, dass, während die Verwendung von festen Größe von integer-Typen bedeutet, dass die Größen der Variablen nicht ändern, wenn der Compiler mit unterschiedlichen Größen für
int
,long
, und so weiter, es wird nicht unbedingt eine Garantie, dass der code verhält sich genauso wie auf Maschinen mit verschiedenen integer-Größen, , auch wenn die Größen definiert sind.Beispiel Erklärung
uint32_t i;
, das Verhalten der Ausdruck(i-1) > 5
wenni
null ist, wird variieren, abhängig davon, ob einuint32_t
ist kleiner alsint
. Auf Systemen, auf denen z.B.int
ist 64 bit (unduint32_t
ist so etwas wielong short
), die variablei
erhalten würden, gefördert zuint
; die Subtraktion und Vergleich kann durchgeführt werden als signed (-1 ist kleiner als 5). Auf Systemen, auf denenint
ist 32 bit, der Subtraktion und Vergleich durchgeführt werden, wieunsigned int
(die Subtraktion ergäbe eine wirklich große Zahl, die größer als fünf sind).Ich weiß nicht, wie viel code stützt sich auf die Tatsache, dass Zwischenergebnisse von Ausdrücken mit unsigned-Typen sind erforderlich, um zu wickeln auch ohne Typumwandlungen (IMHO, wenn das einwickeln Verhalten gewünscht war, sollte der Programmierer einen typecast)
(uint32_t)(i-1) > 5
), aber der standard derzeit keinen Spielraum. Ich Frage mich, welche Probleme gestellt werden, wenn in der Regel, dass mindestens erlaubt einen compiler zu fördern Operanden zu einem mehr integer-Typ in der Abwesenheit von Typumwandlungen oder eine Art Zwang [z.B. gegebenuint32_t i,j
eine Zuordnung wiej = (i+=1) >> 1;
erforderlich sein würde abhacken der überlauf, als würdej = (uint32_t)(i+1) >> 1;
, aberj = (i+1)>>1
würde nicht]? Oder, für diese Angelegenheit, wie schwer wäre es für den compiler-Hersteller zu gewährleisten, dass jede integral-Typ ein Ausdruck, dessen Zwischenergebnisse könnten alle passen in das größte signiert Typ und hat nicht die richtigen Veränderungen, die von nicht-Konstanten Mengen, würde zu den gleichen Ergebnissen, als wenn alle Berechnungen durchgeführt wurden, die auf dieser Art? Es scheint ziemlich eklig zu mir, dass auf einer Maschine, woint
ist 32 bit:löscht ein bit jedes
a
undc
, sondern "nullt" die top 33-bits vonb
; die meisten Compiler geben keinen Hinweis, dass etwas 'anders' sind über einen zweiten Ausdruck.Es ist wahr, dass die Breite einer standard-integer-Typ kann sich ändern, von einer Plattform zur anderen, aber nicht seine minimale Breite.
Beispielsweise der C-Standard legt fest, dass ein
int
ist mindestens16-bit
und einlong
ist mindestens32-bit
breit.Wenn Sie nicht über einige Größe-Einschränkung, wenn die Speicherung Ihrer Objekte, kann man diese an der Umsetzung. Zum Beispiel, wenn Ihre maximale Wert mit Vorzeichen passen in einen
16-bit
können Sie einfach eineint
. Sie lassen dann die Umsetzung das Letzte Wort haben, was es ist, die Natürlicheint
Breite für die Architektur der Implementierung ausgerichtet ist.Sollten Sie nur verwenden, die eine Feste Breite Typen, wenn Sie machen eine Annahme über die Breite.
uint8_t
undunsigned char
sind die gleichen auf den meisten Plattformen, aber nicht auf alle. Mituint8_t
betont auf die Tatsache, dass Sie annehmen, dass eine Architektur mit 8-bit -char
und nicht kompilieren, auf andere, das ist also ein feature.Ansonsten verwende ich den "semantischen"
typedef
wiesize_t
,uintptr_t
,ptrdiff_t
denn Sie spiegeln viel besser, was Sie im Sinn haben, mit Daten. Ich fast nie verwenden Sie die Basis-Typen direktint
nur für Fehler gibt, und ich kann mich nicht erinnern, jemals verwendetshort
.Edit: Nach der sorgfältigen Lektüre der C11 schließe ich, dass
uint8_t
wenn es vorhanden ist, mussunsigned char
und kann nicht nurchar
selbst wenn, der Typ ist nicht signiert ist. Dies kommt von der Anforderung in 7.20.1 p1, dass alleintN_t
unduintN_t
muss die entsprechenden signed und unsigned Typen. Allein für die Charakter-Typen sindsigned char
undunsigned char
.uint8_t
definiert ist,uint8_t
ist immerunsigned char
(oderchar
vorausgesetztchar
ist nicht signiert).char
ist größer als 8 bits werden nicht definierenuint8_t
. Unduint8_t
könnte entwederunsigned char
oder plainchar
(wenn plainchar
ist unsigned und dieCHAR_BIT==8
).uint8_t
nicht kompilieren von code, das ist das, was ich sagte. Ich sehe das als feature, wenn es tatsächlich eine übernahme in den code, müssenCHAR_BIT
zu8
. Für den zweiten Teil, hast du Beispiele für verrückt genug, Architekturen, typedefuint8_t
zuchar
?uint8_t
als nurchar
(oderint8_t
wenn plainchar
signiert ist). Es ist einfacher zu verwendenunsigned char
undsigned char
, aber mit klaremchar
wäre vollkommen legal.Den code zeigen sollte, für den ungeübten Leser (und der Programmierer ihm/Ihr selbst) was wichtig ist. Ist es nur ein integer oder unsigned integer oder sogar Ganzzahl. Das gleiche gilt für die Größe. Ist es wirklich wichtig, den Algorithmus, dass einige variable ist standardmäßig 16-bit? Oder ist das nur unnötiges Mikromanagement und einer gescheiterten versuchen, zu optimieren?
Dies ist, was macht die Programmierung eine Kunst-zu zeigen, was wichtig ist.