Forum: Compiler & IDEs AVR-GCC/ARM-GCC: least significant bits Vorzeichenrichtig


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,
ich habe mal wieder einen C-Knoten im Kopf (naja, es ist diesmal mehr 
ein Zweierkomplementknoten): Ich habe ein Datum, das als 24Bit oder 32 
Bit vorliegt. Davon will ich die letzten beiden Bytes + Vorzeichen 
nutzen, um einen 16-Bit-Integer zu erhalten:
1
int_least24t bigval;
2
uint8_t valLo, valHi;
3
int16_t totalLeast;
4
5
bigval = -1048575;
6
7
valLo = bigval; // ??
8
valHi = bigval < 0 ? (???) : bigval >> 8;
9
10
// Test
11
totalLeast = (valLo + (int16_t) valHi<<8);
Wie berücksichtige ich das Vorzeichen korrekt?

Viele Grüße
W.T.

von Klaus W. (mfgkw)


Lesenswert?

Einfach zuweisen (falls du sicher bist, daß das Ergebnis in 16 Bit 
passt, sonst halt mit Bereichsprüfung vorher):

totalLeast = bigval;

Die oberen Bits fallen dabei automatisch weg, und eine negative Zahl 
bleibt negativ.

von Walter T. (nicolas)


Lesenswert?

Klaus Wachtler schrieb:
> (falls du sicher bist, daß das Ergebnis in 16 Bit
> passt, sonst halt mit Bereichsprüfung vorher)

Ich bin sogar sehr sicher, daß die Zahl nicht in 16 Bit paßt, sondern 
größer ist. Ich will aber nur die letzten Stellen. Sozusagen eine 
Modulo-Operation auf 0x7FFF und dann in zwei Bytes aufteilen. Hm...wenn 
ich drüber nachdenke...

...schlimmstenfalls ist es eine überflüssige Operation, die wegoptimiert 
wird.

Danke für Deine Antwort!

von tictactoe (Gast)


Lesenswert?

Ich denke, dass dir mit
1
totalLeast = bigVal % 0x8000
am besten geholfen ist.

Der C-Standard legt nämlich fest:

"When integers are divided, the result of the / operator is the 
algebraic quotient with any fractional part discarded.[footnote: This is 
often called ‘‘truncation toward zero’’.] If the quotient a/b is 
representable, the expression (a/b)*b + a%b shall equal a; otherwise, 
the behavior of both a/b and a%b is undefined."

Daraus folgt, dass das Ergebnis von a%b das Vorzeichen von a hat.

von Klaus W. (mfgkw)


Lesenswert?

Walter Tarpan schrieb:
> Ich will aber nur die letzten Stellen.

ok, falsch verstanden.
Dann werfe ich das in die Runde:
1
totalLeast = ( bigval<0 ?  ( 0x8000|( bigval&0x7FFF ) ) : ( bigval&0x7FFF ) );

von Walter T. (nicolas)


Lesenswert?

Mit den Anmerkungen von oben geht es einfacher:
1
int_least24t bigval;
2
uint8_t valLo, valHi;
3
int16_t totalLeast;
4
5
bigval = -1048575;
6
7
bigval %= 0x80000;
8
valLo = *(&bigval);
9
valHi = *(&bigval+1);
10
11
// Test
12
totalLeast = (valLo | (int16_t) valHi<<8);
Die unteren Sachen waren nur zur Erläuterung, wie valLo und valHi 
gelesen werden sollten; letztere brauche ich.

Und es funktioniert auch schon alles.

Danke für die Unterstützung.

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.