Forum: Compiler & IDEs Frage zum "guten" Programmierstil bzgl uint8_t


von UBoot-Stocki (Gast)


Lesenswert?

Guten Morgen,

Ich habe in meinem aktuellen Projekt alle (betroffenen) Variablen als 
uint8_t deklariert. In diesen Variablen halte ich Tage, Stunden, Minuten 
und Sekunden einer Uhr. Diese Werte bewegen sich zwischen 0 und maximal 
59.

Bei Einstellen der Uhr tritt u.U. der Fall auf, dass z.B. die Minuten 
per Default auf "00" stehen, die Aktuelle Zeit aber "50" Minuten ist. 
Beim Stellen müsste nun 50x auf den "Minuten+"-Taster gedrückt werden um 
die korrekte Zeit zu stellen. Einfacher wäre es doch den 
"Minuten-"-Taster 10x zu drücken.

Beim ersten Schleifendurchlauf (Minuten auf "00") würde der Druck auf 
"Minuten-" eine negative Zahl produzieren. Da meine Variablen aber als 
"uint8_t" und damit "unsigned" deklariert sind, ändert sich der Wert auf 
255, was in diesem Fall korret ist.

Im Moment habe ich als "Hack" eine Abfrage erstellt, die prüft ob der 
Wert der Minuten-uint8_t-Variable >200 ist. In diesem Fall setze ich die 
Variable auf 59.

Ist das Euerer Meinung nach, im Sinne eines guten, lesbaren 
Programmierstils Ok oder würdet Ihr wegen dieser "Kleinigkeit" das 
gesamte Programm überarbeiten und von uint8_t weggehen auf int8_t. Was 
diverse andere Probleme (casts etc.) mit sich bringen würde ???

Gebt mir bitte mal Euere Meinung ...

Gruß

Andreas

von Andreas K. (a-k)


Lesenswert?

Da die Arithmetik von vorzeichenlosen Typen in C erstens erstens ohne 
Overflow-Trap und zweitens als Modulo-Arithmetik definiert ist, gibt es 
damit m.E. keine Probleme. Bei Typen mit Vorzeichen ist so etwas 
hingegen undefiniert.

Eleganter wär's allerdings, du würdest auf 0 testen, bevor du 
runterzählst.

von Oliver (Gast)


Lesenswert?

Guter Programmierstil ist es, alle Benutzereingaben auf gültige Werte zu 
überprüfen, und auf sinnvollen Werte zu begrenzen.

Also gehören da Abfragen rein, die den Übergang von 59 auf 0, und 
ungekehrt behandeln.

Oliver

von Rahul D. (rahul)


Lesenswert?

Die Abfrage ob = 0 kann man sich doch sparen, wenn man die Variable nach 
dem Inkrementieren/Dekrementieren mit "% 60" behandelt.
Dadurch wird der Zahlenbereich auf Zahlen zwischen 0 und 59 begrenzt.
Da eine unsigned Variable benutzt wird, kommmt es zu einem Überlauf beim 
Übergang von 0 auf -1 (bzw. 255). Wenn man dann 255 % 60 rechnet sollte 
59 herauskommen (kann aber auch sein, dass da was anderes bei 
rauskommt...).

Ob eine Abfrage nicht schneller wäre, sei dahingestellt...

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

keine gute Idee da 255 % 60 = 15
Wenn der Tastendruck "Minuten-" kommt einfach die Variable auf 0 prüfen 
und falls der Vergleich wahr ist Minuten auf 59 setzen sonst eben 
Minuten--. Für "Minuten+" dann analog und fertig.

Matthias

von Simon K. (simon) Benutzerseite


Lesenswert?

Matthias Weißer wrote:
> keine gute Idee da 255 % 60 = 15

Ist doch unwichtig.
1
SekundenHoch()
2
{
3
  sekunden = (sekunden + 1) % 60;
4
}

von UBoot-Stocki (Gast)


Lesenswert?

Hi,

ich versuche immer so einfach wie möglich das Thema abzuhandeln. Der 
entscheidende Tipp kam von Oliver - vielen Dank dafür!

Ich habe es wie folgt gelöst:
1
if (time->hour<23) time->hour++; else time->hour=0;
2
if (time->hour>0) time->hour--; else time->hour=23;

Gruß und Danke

Andreas

von Philipp B. (philipp_burch)


Lesenswert?

@Simon:

Eine Divisionsroutine verwenden, nur um den Bereich einer 
Minuten/Sekunden-Variable einzugrenzen? Finde ich etwas Overkill, zumal 
% 60 ja nicht mit Bitmaskiererei/-schieberei realisiert werden kann...

von Simon K. (simon) Benutzerseite


Lesenswert?

Philipp Burch wrote:
> @Simon:
>
> Eine Divisionsroutine verwenden, nur um den Bereich einer
> Minuten/Sekunden-Variable einzugrenzen? Finde ich etwas Overkill, zumal
> % 60 ja nicht mit Bitmaskiererei/-schieberei realisiert werden kann...

Hey! Ich kam nicht auf die Idee ;) ;)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Warum nimmst du nicht int8_t?  Dein gewünschter Wertebereich passt
ja da noch ordentlich hinein, und du kannst danach ganz legal auf
-1 testen.

von Hagen R. (hagen)


Lesenswert?

was bei unsigned Byte 255 wäre. Entweder auf < 0 oder > 59 nach dem 
Dekremetieren überprüfen und falls es zutrifft +60 draufrechnen. So 
kannst du auch mit zb. 10 dekrementieren.

Gruß Hagen

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hagen Re wrote:

> was bei unsigned Byte 255 wäre.

Bei den meisten Implementierungen. ;-)

Im Ernst: die Portabilität ist nicht garantiert.

> ... auf < 0 ... nach dem
> Dekremetieren überprüfen

"Warning: comparision is always false due to limited data range."

Tu's nicht.  Auf > 59 prüfen geht sicher, aber ist ein Hack.  Wenn
man negative Zahlen erhalten kann, sollte man die Zahlen bitteschön
auch als vorzeichenbehaftet betrachten, warum ist das denn so
schlimm?

von Bobby (Gast)


Lesenswert?

Wie man einen Unsigned Datentyp auf kleiner 0 testen
kann ist mir unbekannt.

Teste daher immer vorher:
Beim Rückwärtszählen auf 0,
Beim Vorwärtszählen auf 59.

Zahlen > 59 bedeuten FEHLER, is klar.

von Hagen R. (hagen)


Lesenswert?

>Tu's nicht.  Auf > 59 prüfen geht sicher, aber ist ein Hack.  Wenn
>man negative Zahlen erhalten kann, sollte man die Zahlen bitteschön
>auch als vorzeichenbehaftet betrachten, warum ist das denn so
>schlimm?

Das bezog sich natürlich darauf das man entweder unsigned oder signed 
benutzt. Ich denke da exakt wie du, warum nicht int8_t benutzen dafür 
ist er da. Bei allem anderen würde ich meine Lehrlinge als Saboteure 
beschimpfen ;)

Mit zwei zugedrückten Augen würde ich vielleicht noch einen Typcast nach 
signed tolerieren, aber auch da wäre es besser gleich den richtigen 
Datentypen zu wählen.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

>Wie man einen Unsigned Datentyp auf kleiner 0 testen
>kann ist mir unbekannt.

indem man diesen hart casted nach signed. Die CPU selber kennt keinen 
signed oder unsigned Datentypen, für sie sind es binäre und 
komplementäre Zahlen, also sowohl unsigned wie auch signed. Erst die 
nachfolgenden Opcodes bei einem Vergleich, also die Auswertung der 
Flags, entscheidet ob man die vorherige Operation -> 
Subtraktion/Addition usw. als signed oder unsigned betrachtet. Aber in 
den Datentypen selber gibts diesen Unterschied nicht (vorrausgesetzt wie 
reden hier von generischen Datentypen die die CPU von Hause aus versteht 
und nicht von selbstgestrickten Datentypen).

Gruß Hagen

von Bobby (Gast)


Lesenswert?

Dann habe ich mich wohl etwas ungeschickt ausgedrückt.

Wenn ein unsigned Typ verwendet wird, dann
gibt es keine negativen Zahlen.

Natürlich kann man hintenrum sowas doch hinbekommen,
ist aber nicht die feine Art.

Ciao.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.