/ / Entschlüsselung von unsigned char * - c ++, linux

Entschlüsselung ohne Vorzeichen char * - c ++, linux

Ich habe einen Prozess, der eine UDP-Multicast-Übertragung abhört und die Daten als nicht signiertes Zeichen * einliest.

Ich habe eine Spezifikation, die Felder innerhalb dieses vorzeichenlosen Zeichens * angibt.

Felder sind in der Spezifikation mit einem Typ und einer Größe definiert.

Typen sind: uInt32, uInt64, unsigned int und Einzelbytezeichenfolge.

Für die Einzelbyte-Zeichenfolge kann ich lediglich auf den Offset des Felds im vorzeichenlosen Zeichen * zugreifen und in ein Zeichen konvertieren, z.

char character = (char)(data[1]);

Singlebyte uint32 Ich habe Folgendes getan, was auch zu funktionieren scheint:

uint32_t integer =  (uint32_t)(data[20]);

Bei Mehrfach-Byte-Konvertierungen scheine ich jedoch festzuhalten.

Wie würde ich mehrere Bytes hintereinander konvertieren? data) zu seinem entsprechenden Datentyp?

Ist es außerdem sicher, Daten in eine Zeichenfolge einzuwickeln (für die Verwendung der Teilzeichenfolge)? Ich bin besorgt darüber, Informationen zu verlieren, da ich unsigniertes Zeichen * an Zeichen * übergeben müsste, wie:

std::string wrapper((char*)(data),length); //Is this safe?

Ich habe so etwas versucht:

std::string wrapper((char*)(data),length); //Is this safe?
uint32_t integer = (uint32_t)(wrapper.substr(20,4).c_str()); //4 byte int

Aber es funktioniert nicht.

Gedanken?


Aktualisieren

Ich habe versucht, die Bitverschiebung vorzuschlagen:

void function(const unsigned char* data, size_t data_len)
{
//From specifiction: Field type: uInt32 Byte Length: 4
//All integer fields are big endian.
uint32_t integer = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3]);
}

Das gibt mir leider Müll (gleiche Nummer für jeden Anruf - von einem Rückruf).

Antworten:

2 für die Antwort № 1

Ich denke, Sie sollten sehr deutlich sein, und nicht Machen Sie einfach "clevere" Tricks mit Casts und Zeigern. Schreiben Sie stattdessen eine Funktion wie folgt:

uint32_t read_uint32_t(unsigned char **data)
{
const unsigned char *get = *data;
*data += 4;
return (get[0] << 24) | (get[1] << 16) | (get[2] << 8) | get[3];
}

Dies extrahiert einen einzelnen uint32_t-Wert aus einem Puffer mit vorzeichenlosen Zeichen und erhöht den Pufferzeiger, um auf das nächste Datenbyte im Puffer zu zeigen.

Dies setzt voraus, dass Big-Endian-Daten vorliegen. Sie müssen eine genaue Vorstellung vom Endian-Modus des Puffers haben, um sie interpretieren zu können.


2 für die Antwort № 2

Abhängig von der Bytereihenfolge des Protokolls, für Big-Endian oder sogenannte Netzwerk-Bytereihenfolge:

uint32_t i = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

0 für die Antwort № 3

Ohne zu kommentieren, ob es eine gute Idee ist oder nicht, besteht der Grund, warum es für Sie nicht funktioniert, darin, dass das Ergebnis von wrapper.substring (20,4) .c_str () (uint32_t *) und nicht (uint32_t) ist. Also wenn du es tust:

uint32_t * integer = (uint32_t *) (wrapper.substr (20,4) .c_str (); es sollte funktionieren.


0 für die Antwort № 4
uint32_t integer = ntohl(*reinterpret_cast<const uint32_t*>(data + 20));

oder (behandelt Ausrichtungsprobleme):

uint32_t integer;
memcpy(&integer, data+20, sizeof integer);
integer = ntohl(integer);

0 für die Antwort № 5

Der Zeigerweg:

uint32_t n = *(uint32_t*)&data[20];

Sie werden jedoch auf verschiedenen Endian-Architekturen auf Probleme stoßen. Die Lösung mit Bitverschiebungen ist besser und konsistenter.

std::string wrapper((char*)(data),length); //Is this safe?

Dies sollte sicher sein, da Sie die Länge der Daten angegeben haben. Andererseits, wenn Sie dies getan haben:

std::string wrapper((char*)data);

Die Länge des Strings würde überall dort bestimmt, wo das erste 0-Byte vorkommt, und Sie werden wahrscheinlich einige Daten abschneiden.