Sauberste Möglichkeit, zwei Shorts zu einem int zu kombinieren

7

Ich habe zwei 16-Bit-Kurzschlüsse (s1 und s2), und ich versuche, sie zu einer einzigen 32-Bit-Ganzzahl (i1) zu kombinieren. Entsprechend der Spezifikation, mit der ich es zu tun habe, ist s1 das signifikanteste Wort, und s2 ist das am wenigsten signifikante Wort, und das kombinierte Wort scheint unterschrieben zu sein. (d. h. das oberste Bit von s1 ist das Vorzeichen.)

Was ist der sauberste Weg, um s1 und s2 zu kombinieren?

Ich dachte mir etwas wie

%Vor%

würde es tun, und es scheint zu funktionieren, aber ich mache mir Sorgen, dass ich um 16 eine Linkskurve wechseln könnte.

Ich bin auch an der Idee interessiert, eine Gewerkschaft zu benutzen, um zu arbeiten, irgendwelche Gedanken darüber, ob das eine gute oder eine schlechte Idee ist?

    
deworde 18.08.2009, 15:30
quelle

7 Antworten

13

Was Sie tun, ist nur dann sinnvoll, wenn die Shorts und der Int alle nicht signiert sind. Wenn eine der Kurzzeichen signiert ist und einen negativen Wert hat, ist die Idee, sie zu einem einzigen int zu kombinieren, bedeutungslos, es sei denn, Sie haben eine domänenspezifische Spezifikation erhalten, um eine solche Möglichkeit abzudecken.

    
anon 18.08.2009 15:35
quelle
6

Was Sie haben, sieht fast korrekt aus, wird aber wahrscheinlich fehlschlagen, wenn der zweite Teil negativ ist; Die implizite Umwandlung in int wird wahrscheinlich die obigen 16 Bits vorzeichenerweitern und mit Einsen füllen. Eine Umwandlung in unsigned short würde das wahrscheinlich verhindern, aber der beste Weg, um sicher zu sein, ist das Maskieren der Bits.

%Vor%     
Mark Ransom 18.08.2009 15:50
quelle
3

Da niemand es gepostet hat, würde die Gewerkschaft so aussehen. Aber die Kommentare über Endian-Ness gelten definitiv.

Big-Endian:

%Vor%

Little-Endian:

%Vor%     
Jonathan 18.08.2009 16:05
quelle
3

Ich weiß, dass dies ein alter Beitrag ist, aber die Qualität der vorliegenden geposteten Antworten ist bedrückend ...

Dies sind die zu beachtenden Punkte:

  • Implizite ganzzahlige Heraufstufung von Kurzschlüssen (oder anderen kleinen Integer-Typen) führt zu einem Operanden vom Typ int , der signiert ist. Dies geschieht unabhängig von der Signedness des kleinen Integer-Typs. Integer-Promotion findet in den Schichtoperationen und im bitweisen OR statt.
  • Im Falle der Verschiebeoperatoren ist der resultierende Typ der des linken Operanden. Bei bitweisem ODER ergibt sich der resultierende Typ aus "den üblichen arithmetischen Umrechnungen".
  • Linksverschiebung einer negativen Zahl führt zu undefiniertem Verhalten. Wenn eine negative Zahl nach rechts verschoben wird, führt dies zu einem implementierungsdefinierten Verhalten (logische vs arithmetische Verschiebung). Daher sollten vorzeichenbehaftete Zahlen nicht zusammen mit Bitverschiebungen in 99% aller Anwendungsfälle verwendet werden.
  • Unionen, Arrays und Ähnliches sind schlechte Lösungen, da sie den Code endanitätsabhängig machen. Darüber hinaus ist der Typ punning through unions in C ++ (im Gegensatz zu C) ebenfalls kein wohldefiniertes Verhalten. Zeigerbasierte Lösungen sind schlecht, weil sie gegen die "strenge Aliasing-Regel" verstoßen.

Eine richtige Lösung wird daher:

  • Verwenden Sie Operanden mit Typen, die garantiert nicht signiert sind und nicht implizit befördert werden.
  • Verwenden Sie Bit-Shifts, da diese Endianess-unabhängig sind.

Es wird so aussehen:

%Vor%

Jede andere Lösung ist sehr fragwürdig und im besten Fall nicht portabel.

    
Lundin 12.05.2017 09:55
quelle
1

Versuchen Sie, Daten zu projizieren. 2. Explizit zu kurzen Typ, wie:

%Vor%

edit: Ich bin C # Entwickler, wahrscheinlich das Casting in Ihrer Code-Sprache sieht anders aus, aber Idee könnte das gleiche sein.

    
twk 18.08.2009 15:34
quelle
0

Sie möchten data.first zunächst auf ein int32-Objekt umwandeln, bevor Sie die Verschiebung vornehmen. Andernfalls wird die Verschiebung den Speicher überlaufen lassen, bevor die Chance besteht, dass sie automatisch heraufgestuft wird, wenn sie kombinierten Daten zugewiesen wird.

Versuchen Sie:

%Vor%

Dies setzt natürlich voraus, dass data.first und data.second Typen sind, die garantiert genau 16 Bit lang sind, sonst haben Sie größere Probleme.

Ich verstehe Ihre Aussage wirklich nicht "wenn Daten.Sekunde zu groß wird, wird die | Tatsache nicht berücksichtigt, dass sie beides sind."

Edit: Und Neil hat absolut recht, wenn es um Signiertheit geht.

    
Tyler McHenry 18.08.2009 15:35
quelle
-1

Die Verwendung einer Union zur Ausführung des Jobs scheint eine gute Wahl zu sein, ist aber aufgrund von Endian-Unterschieden der Prozessoren ein Problem der Portabilität. Es ist machbar, aber Sie müssen bereit sein, Ihre Verbindung basierend auf der Zielarchitektur zu ändern. Bit-Shifting ist portabel, aber bitte schreiben Sie eine Funktion / Methode, um es für Sie zu tun. Inline, wenn Sie möchten.

Was die Signiertheit der Kurzformen betrifft, ist für diese Art von Operation die Bedeutung wichtig, nicht der Datentyp. Mit anderen Worten, wenn s1 und s2 als zwei Hälften eines 32-Bit-Worts interpretiert werden sollen, hat das Setzen von Bit 15 nur dann eine Bedeutung, wenn Sie etwas tun, das bewirkt, dass s2 vorzeichenerweitert wird. Siehe Mark Ransoms Antwort, die besser sein könnte als

%Vor%     
plinth 18.08.2009 15:54
quelle

Tags und Links