Forum: Compiler & IDEs signed byte swapping


von Daniel N. (Gast)


Lesenswert?

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

von Norgan (Gast)


Lesenswert?

Google nach "sign extension" oder lies in einem C-Lehrbuch nach.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Daniel N. (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Daniel N. (Gast)


Lesenswert?

Hast Recht, die Erklärung is für die Tonne...
Hatte die ganze Zeit mit ner -1 getestet und da hats "zufällig" 
funktioniert.

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.