www.mikrocontroller.net

Forum: PC-Programmierung C++ Integer aus Puffer holen


Autor: Thorvin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

Ich schreibe eine Anwendung, die via UDP/IP ein Datenprotokoll 
entgegennimmt und in einen Puffer speichert. In diesem Protokoll stehen 
z.B. die ersten 4 Byte für eine Variable vom Typ "int". Diese möchte ich 
auch als "int" innerhalb meiner Anwendung weiterverwenden.

Problem ist nun, dass diese 4 Byte in anderer Reihenfolge stehen (MSB 
First Byte Order), als dieses im Arbeitsspeicher der Fall ist.

Beispiel: Der Wert 123456789 (=0x075BCD15) steht wie folgt im Protokoll:

07 5B CD 15

...und nicht:

15 CD 5B 07

Erzeuge ich mir also einen int-Zeiger auf diese 4 Byte, dann stimmt der 
Wert nicht.

Im Moment mach ich es so:
Ich erstelle ein char-Array mit der Länge 4, schreibe die Werte dort 
"rückwärts" rein und erzeuge mir einen int-Zeiger darauf. Das 
funktioniert auch wunderbar.

Frage ist: Kennt jemand eine elegantere Lösung, ohne ein zusätzliches 
char-Array erzeugen zu müssen? Und ohne den ursprünglichen Puffer zu 
beeinflussen?

Vielen Dank

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast da verschiedene Probleme auf einmal:
- Als Integer bitte einen uint32_t oder ähnlich, damit du eine feste 
Größe hast, logisch.
- Der Unterschied zwischen Network- und Host-Byte-Order. Dazu enthält 
die GNU-LIBC einige Funktionen, um vom einen ins andere zu kommen.
- Bitordnung, d.h., wo MSBit und LSBit stehen, daran kannst du selten 
etwas ändern, aber denk wenigstens ganz kurz drüber nach :-)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstens garantiert dir niemand, daß int 4 Byte groß ist.
Deshalb macht es eher Sinn, hier int32_t oder uint32_t zu nehmen
(aus stdint.h).

Zweitens:
#include <iostream>
#include <iomanip>
#include <stdint.h>


int main( int nargs, char **args )
{
  unsigned char puffer[4] = { 0x07, 0x5B, 0xCD, 0x15 };

  uint32_t     wert = ( ( (uint32_t)puffer[0] << 24 )
                        |
                        ( (uint32_t)puffer[1] << 16 )
                        |
                        ( (uint32_t)puffer[2] << 8 )
                        |
                        ( (uint32_t)puffer[3] << 0 )
                        );

  std::cout << "wert = 0x" << std::setw(8) << std::setfill('0')
            << std::hex << wert
            << std::endl;
}
In dieser Form ist das Ganze auch portabel zwischen Maschinen mit
Little Endian-Architektur (Intel) und solchen mit
Big Endian-Architektur (fast alle anderen).

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler wrote:
> In dieser Form ist das Ganze auch portabel zwischen Maschinen mit
> Little Endian-Architektur (Intel) und solchen mit
> Big Endian-Architektur (fast alle anderen).
Dann aber bitte statt char auch noch uint8_t.

Zum Verständnis: Schieberei und Rechnerei ist solange portabel, wie man 
sich innerhalb der Grenzen eines Datentypes bewegt. Bricht man daraus 
aus, indem man z.B. vier uint8_t auf einen uint32_t projiziert (struct 
und memcpy, wie auch immer), geht das gerne schief.

Für Worte und Doppelworte bietet sich sowas an:
http://www.gnu.org/software/libc/manual/html_node/...

Für alles andere: Eine Datenstruktur niemals direkt in die Socke 
schreiben, sondern Feld für Feld in geeignete und definierte Typen 
bringen und dann einzeln schreiben. Nachher umgekehrt.

Autor: Thorvin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, das mit den Datentypen fester Größe ist klar, hatte ich am Anfang in 
aller Schnelle nicht drüber nachgedacht.

habe beide Lösungsvorschläge erfolgreich getestet, werde wohl die 
Funktion htonl() verwenden. Vielen Dank dafür!

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.