mikrocontroller.net

Forum: Compiler & IDEs signed byte swapping


Autor: Daniel N. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:

short swap_bytes(short data)
{
    char low, high;
        
    high = (data >> 8) & 0x00FF;
    low = data & 0x00FF;              
        
    return (low << 8) + high;
    
}

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

Autor: Norgan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Google nach "sign extension" oder lies in einem C-Lehrbuch nach.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Daniel N. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:

return (low << 8) | high;


Grüße,
Daniel

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Daniel N. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.