C ++ Wie können zwei vorzeichenbehaftete 8-Bit-Zahlen zu einem 16-Bit-Kurzzeichen kombiniert werden? Unerklärliche Ergebnisse

9

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!

    
Natalie 24.11.2011, 14:11
quelle

7 Antworten

18

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);

    
Retired Ninja 24.11.2011, 14:20
quelle
7

Oder verwenden Sie eine Union:

%Vor%     
Ylisar 24.11.2011 14:51
quelle
2

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?

    
Dan 24.11.2011 14:15
quelle
1

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%     
elmot 16.03.2013 11:33
quelle
1

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.

    
tDwtp 31.05.2014 11:55
quelle
0

Sie haben geschrieben, dass Sie zwei 8-Bit-Werte kombinieren müssen. Warum verwenden Sie unsigned short dann? Wie Dan bereits sagte, wurde lsb automatisch auf 16 Bits erweitert. Probieren Sie den folgenden Code:

%Vor%

Dies gibt Ihnen das erwartete Ergebnis: 499 .

    
maverik 24.11.2011 14:23
quelle
0

Wenn Sie das wollen:

%Vor%

Verwenden Sie dies:

%Vor%

Ich verstehe nicht, warum Sie wollen, dass msb -6 und lsb -1 -6 though generieren.

    
Jan 24.11.2011 14:44
quelle

Tags und Links