Hallo zusammen,
ich bin mal wieder bei einem klassischen Integer-Promotion-Problem. Ich
habe zwei Variablen vom Typ "uint_fast24_t", der -je nach Plattform- als
24-Bit-Integer oder als 32-Bit-Integer ausgebildet ist, von denen ich
vorzeichenrichtig die Differenz bilden will. Etwa so:
1 | // Timer wird in Interrupt hochgezählt
|
2 | int_fast24_t gl_timer_ms;
|
3 |
|
4 | int_fast16_t howLongDoIneed(void)
|
5 | {
|
6 | int_fast16_t diff;
|
7 | uint_fast24_t storetime;
|
8 |
|
9 | storetime = gl_times_ms;
|
10 |
|
11 | // Macht eine wahnsinnig lange Rechnung, die mehrere Millisekunden dauert
|
12 | // ...
|
13 | // ...
|
14 | // ...
|
15 |
|
16 | diff = storetime - gl_times_ms;
|
17 | return diff;
|
18 | }
|
Auf einer 32-Bit-Plattform ist uint_fast24_t == uint32_t. Damit
funktioniert der Überlauf korrekt. Integer Promotion findet zwischen
zwei uint32_t nicht statt, sodaß sich bei der Zuweisung in einen signed
integer immer das richtige Vorzeichen ergibt.
Auf einer 8-Bit-Plattform (AVR) scheint es auch richtig zu funktionieren
- jedenfalls beim Ausprobieren. Hier ist der uint_fast24_t auch
wirklich 24 Bit breit. Also findet keine Integer Promotion statt und die
Differenzbildung findet auf 24Bit Breite statt und die
vorzeichenrichtige Zuweisung an "diff" scheint mir
implementierungsabhängig zu sein.
Aber wie richtet man es richtig ein, daß der gewünschte Zweck
--vorzeichenrichtige Differenz zweier uint24_t -- plattformübergreifend
korrekt ausgeführt wird? Die Variable "diff" wird später in der Breite
16 Bit benötigt.
Viele Grüße
W.T.