Frage

Structs scheinen wie eine nützliche Methode, um ein binäres Blob von Daten (dh eine Datei oder ein Netzwerk-Paket) zu analysieren. Das ist schön und gut, bis Sie variabler Größe Arrays im Blob haben. Zum Beispiel:

struct nodeheader{
        int flags;
        int data_size;
        char data[];
};

Dies ermöglicht es mir, die letzten Datenzeichen zu finden:

nodeheader b;
cout << b.data[b.data_size-1];

Problem Wesen, möchte ich mehrere variabler Länge Arrays haben:

struct nodeheader{
    int friend_size;
    int data_size;
    char data[];
    char friend[];
};

Ich bin die Zuweisung nicht manuell diese Strukturen. Ich habe eine Datei in etwa so:

char file_data[1024];
nodeheader* node = &(file_data[10]);

Als ich versuche, eine binäre Datei (genauer gesagt eine Klasse-Datei) zu analysieren. Ich habe eine Implementierung in Java geschrieben (was meine Klassenzuordnung war), nein, ich bin eine ganz persönliche Version in C ++ zu tun und hatte gehofft, um wegzukommen, ohne 100 Zeilen Code zu schreiben. Irgendwelche Ideen?

Danke, Stefan

War es hilfreich?

Lösung

Sie können nicht mehr variabler Größe Arrays haben. Wie soll der Compiler bei der Kompilierung wissen, wo Freund [] ist? Die Lage von Freund ist abhängig von der Größe der Daten [] und der Größe der Daten ist bei der Kompilierung nicht bekannt.

Andere Tipps

Dies ist ein sehr gefährliches Konstrukt, und ich würde davon abraten. Sie können nur ein variabler Länge Array in einer Struktur enthalten, wenn es das letzte Element ist, und wenn Sie dies tun, müssen Sie sicherstellen, dass Sie genügend Speicher zuweisen, z.

nodeheader *nh = (nodeheader *)malloc(sizeof(nodeheader) + max_data_size);

Was Sie tun mögen, nur regelmäßig dynamisch zugewiesenen Arrays verwenden wird:

struct nodeheader
{
  char *data;
  size_t data_size;
  char *friend;
  size_t friend_size;
};

nodeheader AllocNodeHeader(size_t data_size, size_t friend_size)
{
  nodeheader nh;
  nh.data = (char *)malloc(data_size);  // check for NULL return
  nh.data_size = data_size;
  nh.friend = (char *)malloc(friend_size);  // check for NULL return
  nh.friend_size = friend_size;

  return nh;
}

void FreeNodeHeader(nodeheader *nh)
{
  free(nh->data);
  nh->data = NULL;
  free(nh->friend);
  nh->friend = NULL;
}

Sie können nicht - zumindest nicht in der einfachen Art und Weise, dass Sie versuchen. Die ungeleimtem Array am Ende einer Struktur ist im Grunde ein auf das Ende der Struktur versetzt ist, ohne build-in Art und Weise um das Ende zu finden.

Alle Felder numerische Offsets bei der Kompilierung umgewandelt werden, also müssen sie zu dieser Zeit berechenbar sein.

Die Antworten sind so weit ernst zu verkomplizieren ein einfaches Problem. Mecki ist recht, warum es nicht die Art und Weise getan werden Sie versuchen, es zu tun, aber Sie es in ähnlicher Weise sehr tun können:

struct nodeheader
{
    int friend_size;
    int data_size;
};

struct nodefile
{
    nodeheader *header;
    char *data;
    char *friend;
};

char file_data[1024];

// .. file in file_data ..

nodefile file;
file.header = (nodeheader *)&file_data[0];
file.data = (char *)&file.header[1];
file.friend = &file.data[file->header.data_size];

Für das, was Sie tun, benötigen Sie einen Encoder / Decoder für das Format. Der Decoder nimmt die Rohdaten und Ihre Struktur füllt (in Ihrem Fall Platz für die Kopie eines jeden Abschnitts der Daten Zuteilung) und der Decoder schreibt Raw-Binary.

(War 'Use std :: vector')

Edit:

Ein Feedback zu lesen, nehme ich mir meine Antwort erweitern sollte. Sie können zwei variabler Länge Arrays in Ihrer Struktur effektiv passen wie folgt und die Speicherung wird für Sie automatisch freigegeben werden, wenn file_data aus dem Geltungsbereich:

struct nodeheader {
    std::vector<unsigned char> data;
    std::vector<unsigned char> friend_buf; // 'friend' is a keyword!
    // etc...
};

nodeheader file_data;

Jetzt file_data.data.size (), etc gibt Ihnen die Länge und und & file_data.data [0] gibt Ihnen einen rohen Zeiger auf die Daten, wenn Sie es brauchen.

Sie werden stückchenweise Datei Daten aus der Datei ausfüllen müssen - die Länge der einzelnen Puffer lesen, rufen Sie () auf dem Zielvektor Größe ändern, dann in den Daten lesen. (Es gibt Möglichkeiten, diese etwas effizienter zu machen. Im Zusammenhang mit der Festplattendatei I / O, ich bin es unter der Annahme, keine Rolle spielt).

Im übrigen OP sprüht ist falsch, auch für seine ‚schön und gut‘ Fälle, z.B. mit nur einem VLA am Ende.

char file_data[1024];
nodeheader* node = &(file_data[10]);

Es gibt keine Garantie, dass file_data richtig für die nodeheader Art ausgerichtet ist. Bevorzugen file_data von malloc zu erhalten () -, die einen Zeiger für jede Art ausgerichtet zurückzukehren garantiert - oder auch (besser) erklären den Puffer in erster Linie um den richtigen Typen:

struct biggestnodeheader {
    int flags;
    int data_size;
    char data[ENOUGH_SPACE_FOR_LARGEST_HEADER_I_EVER_NEED];
};

biggestnodeheader file_data;
// etc...
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top