Hallo,
mir ist bekannt, dass in C die größtmögliche Zahl eines uint8_t 255 ist.
Wenn ich nun eine Abfrage wie folgt mache.
1
if(--a==255)a=100;
ist das soweit richtig, aber gerade bei größeren Zahlen hat man die
Max-Werte nicht umbedingt im Kopf.
Gibt es aus der stdint eine Textergänzung/Define, die immer den höchsten
Wert beinhaltet?
Simon schrieb:> Gibt es aus der stdint eine Textergänzung/Define, die immer den höchsten> Wert beinhaltet?
schau doch einfach mal rein in die Header Dateien.
oder einfach mal den ersten Google treffer?
http://www.cplusplus.com/reference/cstdint/
Simon schrieb:> Wenn ich nun eine Abfrage wie folgt mache.
Dann zählst du übrigens wider Erwarten 101 Schritte...
> gerade bei größeren Zahlen hat man die Max-Werte nicht umbedingt im> Kopf.
Du kannst dir die paar für die tägliche Arbeit nötigen Werte doch
einfach merken. Oder noch einfacher: in hex-Notation schreiben.
Die Hex-Notation verwenden halte ich für eine gute Idee. Es erfordert
kein größes Denken und die Intention, den maximalen Wert zu haben, wird
auch deutlich. (mache ich selbst bei chars)
#define schrieb:> #define MAX_UINT8 0xFF // 255
Sollte man nicht selbst definieren brauchen, wenn man eine vernünftige C
Standardbibliothek hat. Da gibt es nämlich bereits UCHAR_MAX.
Mark B. schrieb:> #define schrieb:>> #define MAX_UINT8 0xFF // 255>> Sollte man nicht selbst definieren brauchen, wenn man eine vernünftige C> Standardbibliothek hat. Da gibt es nämlich bereits UCHAR_MAX.
Stimmt, Denken kommt aus der Mode.
Man muss nur die richtige Bibliothek haben.
Mark B. schrieb:> #define schrieb:>> #define MAX_UINT8 0xFF // 255>> Sollte man nicht selbst definieren brauchen, wenn man eine vernünftige C> Standardbibliothek hat. Da gibt es nämlich bereits UCHAR_MAX.
Wenn ich folgender Seite glauben darf:
http://www.cplusplus.com/reference/cstdint/
gibt es auch ein UINT8_MAX.
Ich habe bei meinem oberen Code einen flüchtigkeitsfehler gemacht, ich
meinte statt
Daniel A. schrieb:> gibt es auch ein UINT8_MAX.
Gibt es. Und das sollte man auch verwenden. Ein UCHAR_MAX bringt da
wenig wenn man UINT8_t als Typ verwenden will. Nur weil es hier zufällig
gleich groß ist.
Für alle (U)INTx_t Datentypen gibt es ein define für MAX und für die
vorzeichenbehafteten auch ein MIN.
Simon schrieb:> Hallo,>> mir ist bekannt, dass in C die größtmögliche Zahl eines uint8_t 255 ist.> Wenn ich nun eine Abfrage wie folgt mache.> if(--a == 255) a = 100;
Aaalso - wenn ich nicht irre:
a) bei einem uint8_t würde ich stillschweigend von 255 ausgehen
ansonsten wäre die Bezeichnung irreführend. Wenn ich dann feststellen
würde dass das nicht 255 wären würde ich den Krmepel über Bord werfen
denn wenn bei solch grundlegenden Definitionen schon gepfuscht wird ...
b) Die Bedingung --a == 255 ist schon reichlich merkwürdig. Welche Zahl
aus dem Zahlenraum [0;255] kann - prädekremetiert - 255 ergeben? Das
kann logischerweise nur ein Wraparound von 0 sein. Da würde ich aber
dann stark dran zweifeln wenn ein Programmierer die Bedingung so
unleserlich aufsetzen würde.
rgds
6a66 schrieb:> Simon schrieb:>> Hallo,>>>> mir ist bekannt, dass in C die größtmögliche Zahl eines uint8_t 255 ist.>> Wenn ich nun eine Abfrage wie folgt mache.>> if(--a == 255) a = 100;>> Aaalso - wenn ich nicht irre:>> a) bei einem uint8_t würde ich stillschweigend von 255 ausgehen> ansonsten wäre die Bezeichnung irreführend.
Darum geht's nicht. Der Sinn der bitgenauen Datentypen liegt ja gerade
darin, dass ich die Anzahl der Bits sicher angeben kann. Kenne ich die
Bitanzahl kenne ich auch den MAX Wert. So weit so trivial.
Aber die Verwendung der MAX-Makros verbessert die Leserlichkeit, weil
man hier nicht einfach eine Zahl im Code sieht (was man sowieso
vermeiden sollte) sondern direkt sieht, hier wird absichtlich die größte
/ kleinste mögliche Zahl hergenommen.
Cyblord -. schrieb:> Darum geht's nicht. Der Sinn der bitgenauen Datentypen liegt ja gerade> darin, dass ich die Anzahl der Bits sicher angeben kann. Kenne ich die> Bitanzahl kenne ich auch den MAX Wert. So weit so trivial.
Richtig, das meinte ich.
Cyblord -. schrieb:> Aber die Verwendung der MAX-Makros verbessert die Leserlichkeit, weil> man hier nicht einfach eine Zahl im Code sieht (was man sowieso> vermeiden sollte) sondern direkt sieht, hier wird absichtlich die größte> / kleinste mögliche Zahl hergenommen.
ACK! Das habe ich aus der ursprünglichen Fragestellung aber so nicht
rausgelesen - wenn das der Ansatz war: gut, habe ich daneben geschossen
:(
rgds
Mark B. schrieb:> #define schrieb:>> #define MAX_UINT8 0xFF // 255>> Sollte man nicht selbst definieren brauchen, wenn man eine vernünftige C> Standardbibliothek hat. Da gibt es nämlich bereits UCHAR_MAX.
Es handelt sich nicht um einen unsigned char sondern um einen uint8_t.
UINT8_MAX ist Teil von C99 und wird definiert in stdint.h.
Wolfgang schrieb:>> Sollte man nicht selbst definieren brauchen, wenn man eine vernünftige C>> Standardbibliothek hat. Da gibt es nämlich bereits UCHAR_MAX.>> Stimmt, Denken kommt aus der Mode.> Man muss nur die richtige Bibliothek haben.
Die Verwendung von Bibliotheken hat relativ wenig damit zu tun, nicht
denken zu wollen. Wenn man eine Lösung aus einer Standard-Bibliothek
verwendet, dann kann man auch annehmen, dass die meisten Kollegen, diese
Lösung verstehen / kennen und dass in der Lösung deutlich weniger Fehler
enthalten sind, als in einer eigenen Lösung.
Das setzt natürlich voraus, dass man sich regelmäßig mit den zur
Verfügung stehenden Werkzeugen auseinander setzt.
Simon schrieb:> ist das soweit richtig, aber gerade bei größeren Zahlen hat man die> Max-Werte nicht umbedingt im Kopf.
ja und muss ich doch nicht
Simon schrieb:> if(--a == 255)
würde bei
uint8_t if(--a == 0xFF)
uint16_t if(--a == 0xFFFF)
uint32_t if(--a == 0xFFFFFFFF)
uint64_t if(--a == 0xFFFFFFFFFFFFFFFF)
alternativ den #PRE rechnen lassen
uint8_t if( --a == ((2^8)-1) )
uint16_t if( --a == ((2^16)-1) )
uint32_t if( --a == ((2^32)-1) )
uint64_t if( --a == ((2^64)-1) )
Joachim B. schrieb:> Simon schrieb:>> ist das soweit richtig, aber gerade bei größeren Zahlen hat man die>> Max-Werte nicht umbedingt im Kopf.>> ja und muss ich doch nicht>> Simon schrieb:>> if(--a == 255)>> würde bei> uint8_t if(--a == 0xFF)> uint16_t if(--a == 0xFFFF)> uint32_t if(--a == 0xFFFFFFFF)> uint64_t if(--a == 0xFFFFFFFFFFFFFFFF)>> alternativ den #PRE rechnen lassen> uint8_t if( --a == ((2^8)-1) )> uint16_t if( --a == ((2^16)-1) )> uint32_t if( --a == ((2^32)-1) )> uint64_t if( --a == ((2^64)-1) )
So und jetzt bitte noch (inkl. MIN) für die signed typen. Aber aus dem
Kopf ohne Google ;-)
Aber im Ernst, diese Variante ist einfach umständlich und schwer
leserlich.
Cyblord -. schrieb:> Aber im Ernst, diese Variante ist einfach umständlich und schwer> leserlich.
(hast du da Leseschwierigkeiten?)
mag sein, ist aber eine gültige Antwort die mehr hilft als
Cyblord -. schrieb:> So und jetzt bitte noch (inkl. MIN) für die signed typen. Aber aus dem> Kopf ohne Google ;-)
:-)
Verstehe ich das richtig: Die Größe von Datentypen ist nicht einheitlich
definiert und jeder kann das "Fassungsvermögen" des jeweiligen Typs für
sich selbst nach Gutdünken definieren?
Das fände ich seltsam...
MfG Paul
Joachim B. schrieb:> Cyblord -. schrieb:>> Aber im Ernst, diese Variante ist einfach umständlich und schwer>> leserlich.> (hast du da Leseschwierigkeiten?)> mag sein, ist aber eine gültige Antwort die mehr hilft als
Nein, auf leserlichen Code hinzuweisen hilft immer. Deiner ist es nicht.
Außerdem ist die Methode fehleranfällig. Bei einer 32 Bit Zahl ist
schnell mal ein F vergessen. Und den Fehler suchst du dann ewig und drei
Tage. Ein fertiges Makro aus der Standard lib löst alle diese Probleme
im Handstreich.
> Verstehe ich das richtig
Verstehst du falsch. Bleib bei deinen Anekdoten. Fachlich wird das nix
mehr.
Cyblord -. schrieb:> Verstehst du falsch.
Danke für die ausführliche und wohl begründetet Antwort.
>Bleib bei deinen Anekdoten. Fachlich wird das nix> mehr.
Ja, da hast Du Recht -mit "C" wird das bei mir nichts mehr. Muß aber
auch nicht... Es gibt genügend Alternativen.
MfG Paul
Paul B. schrieb:> Cyblord -. schrieb:>> Verstehst du falsch.> Danke für die ausführliche und wohl begründetet Antwort.
Falls deine Frage ernsthaftes Interesse bekundet werde ich natürlich
gerne Licht in die ewige Finsternis der C-Verächter bringen. Das
gebietet allein schon meine menschenfreundliche Art.
Also:
Datentypen wie int, Long usw. sind in C nicht einheitlich definiert was
die Bitbreite angeht. So ist int meist die native Datenbreite,
mindestens aber 16 Bit. Auf einer 32Bit Maschine daher 32, auf 64 Bit
eben 64. Manchmal will man aber Variablen mit Bitbreiten. Darum gibt es
Makros mit den exakten Bitbreiten (int16_t, uint8_t usw.). Diese werden
dann auf die entsprechenden nativen Datentypen des jeweiligen Systems
gemappt.
Joachim B. schrieb:> alternativ den #PRE rechnen lassen> uint8_t if( --a == ((2^8)-1) )
Soweit ich weiss kann der Preprozessor nicht rechnen, und das "^" steht
für xor. es wäre eher ((1<<8)-1).
Man kann sich auch ein eigenes macro für belibige Datentypen schreiben:
Cyblord -. schrieb:> Falls deine Frage ernsthaftes Interesse bekundet werde ich natürlich> gerne Licht in die ewige Finsternis der C-Verächter bringen.
Na, da bedanke ich mich doch für die vernünftige und sachliche
Erklärung. Das meine ich wirklich so, wie ich es sage.
> Das gebietet allein schon meine menschenfreundliche Art.
Hmm, naja...
Eine Nummer kleiner hätte für das Eigenlob auch genügt...
;-)
MfG Paul
Daniel A. schrieb:> Soweit ich weiss kann der Preprozessor nicht rechnen, und das "^" steht> für xor. es wäre eher ((1<<8)-1).
ist doch egal ob der Preprozessor rechnen kann, der Compiler kann es.
Daniel A. schrieb:> Soweit ich weiss kann der Preprozessor nicht rechnen, und das "^" steht> für xor. es wäre eher ((1<<8)-1).
da hast du recht, ich war im Mathemodus (Exel),
((1<<8)-1) ist hier besser geeignet!
Peter II schrieb:> ist doch egal ob der Preprozessor rechnen kann, der Compiler kann es.
eben, darauf wollte ich hinaus und wenn ich mich recht erinnere tun das
die allermeisten bei Konstanten auch in jeder Art von Optimierung, wird
ja hier immer wieder behauptet.
Mir ist nach mehrmaligem Lesen immer noch nicht klar, warum einer
uint8_t schreibt und sich über den Maximalwert keine Gedanken macht,
stattdessen ein Forum befragt. Ist keinem aufgefallen, dass mich nichts
davon abhält, einem uint16_t auch ein UCHAR_MAX zuzuweisen? Da gibt es
keine syntaktische Absicherung (und wer zählt schon die
Compiler-Warnungen im umgekehrten Fall?)
Solchen Menschen rate ich, lieber mit untypisierten Sprachen zu
arbeiten, das spart viel Wartezeit (bis sich im Forum jemand traut).
Es macht durchaus Sinn, z.B. UINT8_MAX auf eine uint16_t anzuwenden,
z.B. vor einer Zuweisung einer uint16_t an ein uint8_t.
ich persönlich ziehe UINT8_MAX auch einem 255 oder 0xff vor, da damit
deutlich wird, daß es sich um den Maximlwert und nicht um irgendeine
Zahl, die zufällig dem Maximalwert entspricht, handelt.
Gruß, Stefan
Boris O. schrieb:> Ist keinem aufgefallen, dass mich nichts davon abhält, einem uint16_t auch > ein
UCHAR_MAX zuzuweisen?
Kann man machen, da es ein gültiger wert ist. Ist halt nicht unbedingt
guter Programmierstil. Von fragwürdigem Programmierstil hält einen
keiner ab, erst recht nicht der C-Compiler.
Man kann übrigens auch einem uint8_t eine Konstante zuweisen, die größer
ist als das was in uint8_t hineinpasst. Wird zwar eine Warnung geben,
aber akzeptiert wird es.
Paul B. schrieb:> Verstehe ich das richtig: Die Größe von Datentypen ist nicht einheitlich> definiert und jeder kann das "Fassungsvermögen" des jeweiligen Typs für> sich selbst nach Gutdünken definieren?
Zumindest bei int bzw. uint hast du IMHO aber leider Recht. Da legt der
Compiler- bzw. Prozessorhersteller fest, welches der "natürliche"
Ganzzahltyp ist.
Mark B. schrieb:> Wird zwar eine Warnung geben,> aber akzeptiert wird es.
Compilerwarnungen finde erst mal gut und schalte sie wo ich kann ein.
Es gibt aber auch Warnungen gerade im char Sektor die nerven nur, weil
es mal signed mal unsigned char gibt, ich frage mich dann immer wieder
wieso char mit dem Atribut signed oder unsigned geführt wird oder ob
char nicht bei 127 enden müsste ascii oder ob char bis 255 gehen dürfen?
Aber getch ist wohl immer 16-bittig, muss am DOS liegen, jedenfalls
nichts ist verwirrender als char, ich weiss das ein char ein Zeichen ist
und ein Zeichen 8-bit hat, aber das war es auch schon, deswegen ist mir
die neuere Schreibweise uint8_t auch sympatisch, aber nicht auf
Stringroutinen anwendbar.
Joachim B. schrieb:> ich weiss das ein char ein Zeichen ist> und ein Zeichen 8-bit hat, aber das war es auch schon, deswegen ist mir> die neuere Schreibweise uint8_t auch sympatisch, aber nicht auf> Stringroutinen anwendbar.
Ob ein Zeichen aus 8 bit besteht und ein char ein ganzes Zeichen
räpresentiert ist von der Codierung abhängig, und wieviele bit der char
Datentyp hat ist von der CPU abhängig und steht in der variable
CHAR_BIT, welche in limits.h definiert ist.
Joachim B. schrieb:> Aber getch ist wohl immer 16-bittig, muss am DOS liegen,
Das liegt daran, dass auch noch EOF codiert werden muss.
Joachim B. schrieb:> jedenfalls> nichts ist verwirrender als char,
Es gibt drei Typen von char:
char ist für Zeichen (und Strings) da.
signed char für Integer mit Vorzeichen und kleinem Wertebereich
unsigned char für Integer ohne Vorzeichen und kleinem Wertebereich
Dirk B. schrieb:> Es gibt drei Typen von char:> char ist für Zeichen (und Strings) da.> signed char für Integer mit Vorzeichen und kleinem Wertebereich> unsigned char für Integer ohne Vorzeichen und kleinem Wertebereich
Autsch, da würde ich noch mal drüber nachdenken.
Michael K. schrieb:> Autsch, da würde ich noch mal drüber nachdenken.
So benutze ich es aber auch, wenn der Speicher knapp ist. Da sowohl
char, signed und unsigned genau definiert sind, sollte das meines
Wissens keine Probleme geben, wenn man weiß, was man macht.
Dussel schrieb:> Da sowohl> char, signed und unsigned genau definiert sind,
sind falsche Annahmen, bezogen auf char und signed oder unsigned, nicht
der erste gemachte Fehler?
Joachim B. schrieb:> sind falsche Annahmen, bezogen auf char und signed oder unsigned, nicht> der erste gemachte Fehler?
Wie meinst du das? Soweit ich weiß, hat ein char immer acht Bit,
unsigned ist die normale Binärdarstellung und signed die Darstellung im
Zweierkomplement. Ich denke, dass das so im Standard definiert ist, aber
auch wenn nicht, sollte das für weit über 90% der Fälle passen.
Dussel schrieb:> Soweit ich weiß, hat ein char immer acht Bit
Nein. Es hat nur mindestens acht Bit, und es ist definiert, dass
es sich dabei um die kleinste adressierbare Einheit hat.
Es spricht aus Sicht des Standards jedoch nichts dagegen, dass ein
char bspw. 32 Bit hat. Allerdings kann es auf so einer Architektur
dann kein uint8_t geben (jedoch uint_least8_t sowie uint_fast8_t).
Jörg W. schrieb:> Es hat nur mindestens acht Bit, und es ist definiert, dass> es sich dabei um die kleinste adressierbare Einheit hat.
"…handelt"?
Interessant, das wusste ich nicht. Dann bleibt aber noch der zweite Teil
meiner Aussage. Gibt es in nennenswertem Umfang Systeme, bei denen ein
char mehr als acht Bit hat? XCode gibt auf meinem x64 ein Byte als Größe
eines chars aus.