Konvertieren Sie ein uint16_t in char[2] soll über Socket gesendet werden (Unix)

Lesezeit: 5 Minuten

Benutzeravatar von Michael Crook
Michael Crook

Ich weiß, dass es da draußen ungefähr Dinge gibt. Aber mein Gehirn tut weh und ich kann nichts finden, damit das funktioniert …

Ich versuche, eine 16-Bit-Ganzzahl ohne Vorzeichen über einen Unix-Socket zu senden. Dazu muss ich ein uint16_t in zwei Zeichen umwandeln, sie dann am anderen Ende der Verbindung einlesen und wieder in eines umwandeln unsigned int oder ein uint16_t, an diesem Punkt spielt es keine Rolle, ob es 2 Bytes oder 4 Bytes verwendet (ich verwende 64 Bit, deshalb kann ich kein unsigned int verwenden 🙂

Ich mache das übrigens in C

Danke

  • Ich werde es versuchen, wenn ich von der Uni nach Hause komme :\ Dieses Semester war die Hölle, alles lief schrecklich … Ich habe so viele Verlängerungen bekommen, jetzt sind alle meine Aufgaben in der Studienpause … Schade, dass das Studium nicht möglich ist Erweiterung =.= Ich muss zur Uni für eine Physik-Revisionsdiskussion. Vielen Dank an alle für die schnellen Antworten

    – Michael Crook

    8. November 2012 um 5:21

  • Sind Sie sicher, dass Sie es verwenden möchten? einfaches Zeichen und nicht unsigniertes Zeichen – oder noch besser uint8_t?

    – Andreas

    8. November 2012 um 6:31

Benutzeravatar von Steven Sudit
Steven Sudit

Warum nicht einfach mit Maske und Verschiebung in Bytes aufteilen?

 uint16_t value = 12345;
 char lo = value & 0xFF;
 char hi = value >> 8;

(bearbeiten)

Am anderen Ende bauen Sie es in umgekehrter Reihenfolge zusammen:

 uint16_t value = lo | uint16_t(hi) << 8;

Ich bin mir spontan nicht sicher, ob dieser Gipsverband erforderlich ist.

  • Nun, diese Antwort hat mir viel Ärger erspart, selbst nachdem ich sie über ein Jahr nach dem Schreiben verwendet habe. Danke.

    – Marek

    7. September 2013 um 13:47 Uhr

  • Und ein Jahr später ist es immer noch nützlich, also hören Sie nicht auf, gute Stimmung zu verbreiten

    – ruisea

    21. Februar 2014 um 23:49 Uhr

  • Tut mir leid, ich habe die Frage ganz vergessen … Ich habe einen Frühjahrsputz in meinem Profil gemacht und das bemerkt und mich geirrt 🙁 Habe hier die richtige Antwort gegeben, seit ich das vor einer Million Jahren getan habe, da klingeln bei mir die Glocken Habe es geschafft… Außerdem scheint die Antwort allen zu gefallen. Sorry @StevenSudit

    – Michael Crook

    9. Okt. 2014 um 2:59

  • Ich mache das wahrscheinlich falsch, aber das Gegenteil funktioniert bei großen Zahlen nicht 36345 es sei denn, ich wirke lo zu einem uint8_t Erste. uint16_t value = (uint8_t)lo | hi << 8;

    – Teynon

    22. Januar 2021 um 4:14

Goz' Benutzer-Avatar
Goz

char* pUint16 = (char*)&u16;

dh Wandeln Sie die Adresse von uint16_t um.

char c16[2];
uint16_t ui16 = 0xdead;
memcpy( c16, ui16, 2 );

c16 enthält nun die 2 Bytes von u16. Am anderen Ende können Sie den Vorgang einfach umkehren.

char* pC16 = /*blah*/
uint16_t ui16;
memcpy( &ui16, pC16, 2 );

Obwohl es einen Aufruf von memcpy gibt, wird interessanterweise fast jeder Compiler ihn optimieren, da er eine feste Größe hat.

Wie Steven Sudt betont, kann es zu Problemen mit Big-Endian kommen. Um dies zu umgehen, können Sie die Funktion htons (kurz Host-to-Network) verwenden.

uint16_t ui16correct = htons( 0xdead );

und am anderen Ende verwenden Sie ntohs (kurz Network-to-Host)

uint16_t ui16correct = ntohs( ui16 );

Auf einer Little-Endian-Maschine wird dadurch die Short-Datei in Big-Endian-Datei konvertiert und dann am anderen Ende wieder von Big-Endian-Datei zurückkonvertiert. Auf einer Big-Endian-Maschine bewirken die beiden Funktionen nichts.

Natürlich, wenn Sie wissen Stellen Sie sicher, dass die Architektur beider Maschinen im Netzwerk die gleiche Endian-Näherung verwendet, dann können Sie diesen Schritt vermeiden.

Suchen Sie nach ntohl und htonl für die Verarbeitung von 32-Bit-Ganzzahlen. Die meisten Plattformen unterstützen auch NTOHLL und HTONLL für 64-Bit.

  • Ok, das gibt Ihnen einen char-Zeiger auf int16, aber was Sie im ersten Element finden, hängt von Big-Endian vs. Small-Endian ab.

    – Steven Sudit

    7. November 2012 um 22:10 Uhr

  • Sie haben Recht, dass memcpy normalerweise optimiert wird, aber das ist es still systemabhängig von großen/kleinen Unternehmen.

    – Steven Sudit

    7. November 2012 um 22:12 Uhr

  • Ok, das ist besser, aber es scheint, als wäre ntohs() für etwas, das ziemlich einfach ist, viel Aufwand.

    – Steven Sudit

    7. November 2012 um 22:25

  • Das ist es wirklich nicht … auf vielen Plattformen ist es eine einzige Anweisung. Andererseits ist es nur ein Anweisungsmodifikator … Ich würde mir darüber keine Sorgen machen, ehrlich gesagt.

    – Goz

    7. November 2012 um 22:27

  • @StevenSudit Der Overhead für Funktionsaufrufe beträgt 0, wenn die Funktion eingebunden wird und jeder vernünftige Compiler eine einzeilige Funktion einfügt. Er ist nicht „riesig“.

    – Etienne

    10. Februar 2014 um 16:01 Uhr

Klingt, als müssten Sie das verwenden Bitmasken- und Verschiebungsoperatoren.

So teilen Sie eine 16-Bit-Zahl in zwei 8-Bit-Zahlen auf:

  • Sie maskieren die unteren 8 Bits mit dem bitweisen UND-Operator (& in C), sodass die oberen 8 Bits alle 0 werden, und weisen dieses Ergebnis dann einem Zeichen zu.
  • Sie verschieben die oberen 8 Bits mit dem rechten Verschiebungsoperator (>> in C) nach rechts, sodass die unteren 8 Bits alle aus der Ganzzahl herausgeschoben werden und nur die oberen 8 Bits übrig bleiben, und weisen diese einem anderen Zeichen zu.

Wenn Sie dann diese beiden Zeichen über die Verbindung senden, machen Sie das Gegenteil: Sie verschieben die ehemaligen oberen 8 Bits um 8 Bits nach links und kombinieren sie dann bitweise ODER mit den anderen 8 Bits.

Gianluca Ghettinis Benutzeravatar
Gianluca Ghettini

Grundsätzlich senden Sie 2 Bytes über den Socket, das ist alles, was der Socket wissen muss, unabhängig von Endianness, Signiertheit usw. Zerlegen Sie einfach Ihr uint16 in 2 Bytes und senden Sie sie über den Socket.

char byte0 = u16 & 0xFF;
char byte1 = u16 >> 8;

Führen Sie am anderen Ende die Konvertierung in umgekehrter Reihenfolge durch

1453020cookie-checkKonvertieren Sie ein uint16_t in char[2] soll über Socket gesendet werden (Unix)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy