Ich muss zwei vorzeichenbehaftete 8 Bit _int8 Werte mit einem vorzeichenbehafteten kurzen (16 Bit) Wert kombinieren. Es ist wichtig, dass das Zeichen nicht verloren geht.
Mein Code ist:
%Vor%Das Ergebnis ist -13. Allerdings erwarte ich, dass es 499 ist.
Für die folgenden Beispiele bekomme ich die richtigen Ergebnisse mit dem gleichen Code:
msb = -1; lsb = -6; kombiniert = -6;
msb = 1; lsb = 89; kombiniert = 345;
msb = -1; lsb = 13; kombiniert = -243;
Jedoch ist msb = 1; lsb = -84; kombiniert = -84; wo ich 428 erwarten würde.
Es sieht so aus, als ob der LSB negativ ist und der MSB positiv ist. Was ist falsch an meinem Code? Wie kommt der Computer zu diesen unerwarteten Ergebnissen (Win7, 64 Bit und VS2008 C ++)? Vielen Dank für jede Hilfe!
Ihr lsb enthält in diesem Fall 0xfff3. Wenn Sie es mit 1 & lt; & lt; 8 ändert sich nichts, weil in dieser Bitposition bereits eine 1 ist.
Versuchen Sie short combined = (msb << 8 ) | (lsb & 0xff);
Es ist möglich, dass lsb
automatisch auf 16 Bit vorzeichenerweitert wird. Ich bemerke, dass Sie nur ein Problem haben, wenn es negativ ist und msb positiv ist, und das ist es, was Sie erwarten würden, wenn Sie den Operator oder verwenden. Obwohl du hier eindeutig etwas sehr Seltsames tust. Was versuchst du eigentlich hier zu machen?
Der Raisonanse C-Compiler für STM8 (und möglicherweise auch viele andere Compiler) generiert hässlichen Code für klassischen C-Code beim Schreiben von 16-Bit-Variablen in 8-Bit-Hardware-Register. Hinweis - STM8 ist Big-Endian, für Little-Endian-CPUs muss der Code leicht modifiziert werden. Lesen / Schreiben der Byte-Reihenfolge ist ebenfalls wichtig.
Also, Standard-C-Codestück:
%Vor%Wird kompiliert nach:
%Vor%Zu lang, zu langsam.
Meine Version:
%Vor%Das wird in zwei adäquate MOVes kompiliert
%Vor%Gegenrichtung:
%Vor%statt
%Vor%Einige Dinge, die Sie über die Datentypen wissen sollten ( un ) signiert kurz und char :
char ist ein 8-Bit-Wert, nach dem Sie auf der Suche nach lsb und msb suchen. short ist 16 Bit lang.
Sie sollten signierte Werte auch nicht in unsignierten Werten speichern, außer Sie wissen, was Sie tun.
Sie können sich die Zweierkomplement ansehen. Es beschreibt die Darstellung negativer Werte (für Integer, nicht für Fließkommawerte) in C / C ++ und vielen anderen Programmiersprachen.
Es gibt mehrere Versionen, die Ihr eigenes Zweierkomplement machen:
%Vor%stdint.h (mit inttypes.h) ist mehr für den Zweck, genaue Längen zu haben deine Variable. Wenn Sie wirklich eine Variable benötigen, um eine bestimmte Byte-Länge zu haben, sollten Sie diese verwenden (hier brauchen Sie sie).
Sie sollten alle Datentypen verwenden, die Ihren Bedürfnissen am besten entsprechen. Ihr Code sollte daher wie folgt aussehen:
%Vor%oder wie folgt:
%Vor%Beim letzten Mal verwendet der Compiler immer 8/16-Bit-Werte, unabhängig davon, welche Länge int auf Ihrer Plattform hat. Wikipedia hat einige nette Erklärungen zu den Datentypen int8_t und int16_t erhalten ( und alle anderen Datentypen).
btw: cppreference.com ist nützlich, um die ANSI C Standards und andere Dinge, die man über C / C ++ wissen sollte.