Serializzare strutture dati in C [chiuso]

6

Recentemente ho letto tre libri separati su algoritmi e strutture dati, programmazione tcp / ip socket e programmazione con memoria. Il libro sulla memoria ha brevemente discusso l'argomento della serializzazione delle strutture di dati allo scopo di memorizzarlo su disco o inviarlo attraverso una rete. Non posso fare a meno di chiedermi perché gli altri due libri non abbiano affatto discusso della serializzazione.

Dopo una ricerca web / libro fallita mi chiedo dove posso trovare un buon libro / carta / tutorial sulla serializzazione delle strutture dati in C? Dove o come l'hai imparato?

    
posta Nocturno 11.10.2012 - 22:09
fonte

5 risposte

12

C non ha supporto nativo per la serializzazione delle strutture, quindi sei da solo.
L'approssimazione del primo ordine è (come indicato in altre risposte) per definirlo per i tipi primitivi e applicarlo ricorsivamente a strutture più grandi.

Tuttavia, ci sono molti dettagli diabolici che devono essere affrontati al di là del concetto semplice. Per citarne alcuni:

  • ordine endico di numeri interi e dimensioni di vari tipi comuni di numeri interi dipendenti su architetture di macchine. Questo non è un grosso problema se tutti i consumatori di serializatin sono lo stesso binario, ma considerano la lettura dei dati prodotti da un Mac PPC a 32 bit su una macchina Windows a 64 bit o se un "long" è di 32 o 64 bit.
  • Rappresentazioni diverse per tipi di dati comuni. Le bitmap a colori hanno 3 componenti su un PC, ma 4 componenti, in un ordine diverso, su Mac
  • Rappresentazione e precisione dei numeri in virgola mobile.
  • Se le stringhe con le stesse lettere sono identiche o solo simili.
  • che si occupa di strutture dati cicliche o autoreferenziali.
risposta data 12.10.2012 - 00:00
fonte
7

Dai un'occhiata al lavoro svolto da Google con Protocollo buffer .

Scrivi un file .proto in questo modo:

message Person {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;
}

Quindi lo compili con protoc, il compilatore del buffer di protocollo, per produrre codice in C ++, Java o Python.

Quindi, se stai usando C ++, usi quel codice come questo:

Person person;
person.set_id(123);
person.set_name("Bob");
person.set_email("[email protected]");

fstream out("person.pb", ios::out | ios::binary | ios::trunc);
person.SerializeToOstream(&out);
out.close();

Puoi esaminare il metodo SerializeToOstream per capire in che modo Google genera il codice di serializzazione. Sì, è un codice C ++, ma dovrebbe comunque essere abbastanza vicino al codice C.

    
risposta data 11.10.2012 - 22:34
fonte
4

L'articolo di Wikipedia Serializzazione copre l'argomento abbastanza bene, sebbene stranamente non menzioni ASN.1 che è uno standard ampiamente odiato, ma estremamente ben definito e ben noto per la descrizione di protocolli efficienti di serializzazione dei dati. I compilatori ASN tipicamente generano codice (ad esempio codice C) per codificare e decodificare le strutture di dati descritte in modo canonico.

A proposito, il problema endian può essere affrontato banalmente in C, come Rob Pike ha mostrato bene nel suo articolo The Byte Order Fallacy , sebbene alcuni compilatori C non generino sempre il codice oggetto più ottimale quando si utilizza questa tecnica.

    
risposta data 19.11.2012 - 01:04
fonte
3

Probabilmente non era coperto nei tuoi libri perché ci sono così tante varianti possibili, tutti diversi compromessi tra velocità di runtime, facilità d'uso e portabilità.

Ad esempio, 1 e 3 sono praticamente le estremità opposte dello spettro e 2 mostra solo il numero di piccole variazioni possibili tra loro:

  1. Non serializzare, copia semplicemente i byte non elaborati

    • questo ti lascia dipendente dall'architettura e dai dettagli del compilatore (endianness, padding & alignment, rappresentazione in virgola mobile), quindi very non-portable
    • non funziona affatto (extra), quindi molto veloce
    • non gestisce alcuna forma di indirezione, quindi funziona solo per strutture POD piatte e autonome
    • è un dolore assoluto da decodificare, se ne hai bisogno per il debug
  2. come 1, ma specificare esplicitamente padding, alignment e endianness

    • questo è ora portatile, al costo aggiuntivo minimo delle conversioni di ordine dei byte (su host con ordine di byte nativo diverso da quello specificato) e il requisito di forzare l'allineamento appropriato (che potrebbe non essere ottimale su tutte le architetture)
  3. serializza tutto in un formato di testo come XML o JSON

    • questo è molto portatile
    • e molto lenti (relativamente)
    • puoi farlo gestire in modo indiretto, inclusi i riferimenti circolari, se hai bisogno di
    • è davvero facile leggere direttamente i messaggi serializzati

Oh, e ho imparato a conoscere questa roba (tutto quanto sopra, oltre a CORBA, ASN.1 e ProtocolBuffers) implementando i protocolli documentati esistenti.

Se il tuo obiettivo principale è la portabilità piuttosto che la velocità, qualcosa verso l'estremità n. 3 dello spettro è probabilmente una soluzione migliore. Per quanto riguarda come lo hai costruito in primo luogo, è quasi più una questione di riflessione.

    
risposta data 15.10.2013 - 13:13
fonte
-1

La serializzazione è in genere piuttosto semplice e ricorsiva. Devi solo capire quali campi devi inviare prima dei dati reali in modo da poter ricostruire la struttura dall'altra parte. I problemi sarebbero principalmente endianness. Imparalo per tentativi ed errori, dubito che tu abbia bisogno di un libro per questo genere di cose.

    
risposta data 11.10.2012 - 22:32
fonte

Leggi altre domande sui tag