Forum: Mikrocontroller und Digitale Elektronik Subtraktion zweier uint8 geht schief?


von Arian (Gast)


Lesenswert?

Hallo,

ich versteh da was nicht, vielleicht helft ihr mir auf die Sprünge.
(Der Code unten handelt von einem Sekundenzähler, der einen 
Minutenzähler inkrementieren soll.)
Beispielcode:

uint8_t a; // SekundenZähler
uint8_t b; // SekundenZählerStempel

a = 59;
b = 255;

if( (a - b) == 60)
{
   ...minutenzähler hier hochzählen...
}


Der Code oben führt leider nicht zur korrekten Inkrementierung, während 
dieser hier funktioniert.

if( (uint8_t)(a - b) == 60)
{
   ...minutenzähler hier hochzählen...
}

Sieht so aus als ob in der oberen Subtraktion nicht mit uint8 Typen 
gearbeitet wird, da es mit dem Cast auf uint8 funktioniert es.

Meine Frage: warum muss ich dem Compiler extra sagen, dass er auf uint8 
beschränken muss, obwohl alle beteiligten Typen ja uint8 sind?

Gruß,
Arian

von hubert (Gast)


Lesenswert?

Arian schrieb:
> a = 59;
> b = 255;
>
> if( (a - b) == 60)
> {
>    ...minutenzähler hier hochzählen...
> }

uint8_t ist unsigned, also vorzeichenlos unt geht von 0...255

59-255 ist aber negativ.

hubert

von Stefan E. (sternst)


Lesenswert?

Arian schrieb:
> Meine Frage: warum muss ich dem Compiler extra sagen, dass er auf uint8
> beschränken muss, obwohl alle beteiligten Typen ja uint8 sind?

Weil der C-Standard vorschreibt, dass alle Berechnungen/Vergleiche 
mindestens in int zu erfolgen haben. Im ersten Beispiel werden a und b 
nach int gewandelt, subtrahiert und dann das int-Ergnebnis mit 60 
verglichen. Im zweiten Fall läuft es so: a und b werden nach int 
gewandelt und subtrahiert, das int-Ergebnis wird dann wegen des Cast auf 
uint8_t gestutzt, das wird dann wieder nach int gewandelt und mit 60 
verglichen.

von Arian (Gast)


Lesenswert?

@Hubert: unsigned kann man voneinander subtrahieren, auch wenn der 
Subtrahend größer als der Minuend ist. In diesem Fall wird die Differenz 
trotzdem korrekt berechnet - vorausgesetzt es wird auch im richtigen Typ 
(uint8) gerechnet.

@Stefan Ernst:
Besten Dank für die Erklärung, sehr hilfreich. Das heißt für mich, wenn 
ich in Zukunft Zähler mit Überlauf anlege, und der Bereich 0..127 
ausreicht, bin ich mit einem signed besser dran, weil ich dann in 
Subtraktionen usw. nicht an casts denken muss.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Arian schrieb:

> Das heißt für mich, wenn
> ich in Zukunft Zähler mit Überlauf anlege, und der Bereich 0..127
> ausreicht, bin ich mit einem signed besser dran, ...
Signed-Überlauf ist undefined.

von Arian (Gast)


Lesenswert?

Johann L. schrieb:
> Signed-Überlauf ist undefined.

D.h. ich komm um den Cast nicht rum.

Wundert mich dass ich das Problem nur beim ATMEL merke. Eventuell 
kümmern sich andere Compiler wie der von TI implizit darum.

von (prx) A. K. (prx)


Lesenswert?

Arian schrieb:

> Wundert mich dass ich das Problem nur beim ATMEL merke. Eventuell
> kümmern sich andere Compiler wie der von TI implizit darum.

Ein Compiler, der sich nicht so verhält, wie du im ersten Posting 
schilderst, der arbeitet nicht korrekt.

Es gibt Compiler für 8-Bit Maschinen, die optional oder per default die 
implizite int-Konvertierung unterlassen. Das entspricht dann nicht dem 
Standard, erzeugt aber kürzeren Code.

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.