signed byte swapping

Gast #786792
Hi,

ich habe eine Funktion geschrieben, welche die Bytes eines shorts 
tauscht.
Im Prinzip keine große Kunst. Allerdings soll dies auch mit signed Daten 
funktionieren. Meine byte swap Funktion sah zu begin so aus:

1
short swap_bytes(short data)
2
{
3
    char low, high;
4
        
5
    high = (data >> 8) & 0x00FF;
6
    low = data & 0x00FF;              
7
        
8
    return (low << 8) + high;
9
    
10
}

Wenn ich die Funktion zwei mal hintereinander aufrufe,
sollte man meinen, dass man wieder seine Anfangszahl erhält.
Dem ist aber nicht so. Wenn ich z.B. eine "-3" reingebe,
gibt die Funktion mir "-769" zurück. Rufe ich die Funktion nun mit 
diesem Ergebnis auf, erhalte ich nicht die erwartete "-3", sondern 
"-260".

Deklarier ich das low und high byte aber als unsigned char,
funktioniert es tadellos.

Kann mir jemand erklären wieso sich das so verhält?


Grüße,
Daniel
Moderator Persönliche Seite
Byteswap bei vorzeichenbehafteten Zahlen hat so keinen Sinn.  Die
Bytes sind immer in sich vorzeichenlos (Bytes eben).  Eine
Interpretation als vorzeichenbehaftet kann erst danach erfolgen
("swap in") oder aber wird in diesem Moment aufgegeben ("swap out").

"char" ist übrigens in diesem Zusammenhang ganz schlecht, da es
nicht klar ist, ob es vorzeichenbehaftet ist oder nicht.  Wenn du
ISO-C99-mäßig <stdint.h> hast, dann benutze uint8_t bzw. int8_t.
Gast
Danke für eure Antworten.

Mein Problem war eher zu verstehen, wieso es einen Unterschied macht, ob 
ich das low und high byte als unsigned char oder signed char deklariere.

Ich bin dem "Problem" nun aber auf die Schliche gekommen.
Für alle die es auch interessiert, mache ich mal eine Beispiel mit der 
-2.

Negative Zahlen werden im 2er-Komplement dargestellt. Die -2 sieht bei 
einem short also so aus 11111111 11111110.

Die Variable "high" wird jetzt mit 11111111 (dez: -1) und die Variable 
"low" mit 11111110 (-2) gefüllt.

Beim return schieb ich das low byte erstmal um 8Bit nach links.
Zu dem Zeitpunkt sieht der Returnwert so aus: 11111110 00000000 (-512).
Jetzt muss das untere byte des Returnwerts noch mit dem high byte 
gefüllt werden. Dazu habe ich eine Addition gewählt, was das eigentliche 
Problem war. Der Compiler addiert jetzt zu der (-512) das high byte, 
welches er als -1 interpretiert.
Und -512 + -1 sind nunmal -513.

Richtig wäre es gewesen, anstatt der Addition eine simple 
Oder-Verknüpfung zu wählen...

Die letzte Zeile säh dann also so aus:
1
return (low << 8) | high;

Grüße,
Daniel
Daniel N. wrote:

> Dazu habe ich eine Addition gewählt, was das eigentliche
> Problem war.

Quatsch, Addition und links Schieben ists wurscht, die funktionieren bei 
signed und unsigned gleich.


Der Fehler entsteht bei der Formatumwandlung 8bit -> 16 Bit, da macht 
die signed Routine eine Vorzeichenerweiterung (kopiert Bit7 nach 
Bit8..15).


Peter

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.