2014-06-30 10 views
5

Ciao, sono nuovo di questo sito e ho bisogno di aiuto per capire cosa sarebbe considerata la "norma" durante la codifica delle strutture in C che richiedono una stringa. Fondamentalmente mi chiedo quale dei seguenti modi potrebbe essere considerato il "standard" durante l'utilizzo di strutture in C per tenere traccia di tutta la memoria della struttura richiede:Come dovrei dichiarare le stringhe all'interno delle strutture C?

1) Fixed Size Stringa:

typedef struct 
{ 
    int damage; 
    char name[40]; 
} Item; 

ora posso ottenere la dimensione utilizzando sizeof(Item)

2) Character Array Pointer

typedef struct 
{ 
    int damage; 
    char *name; 
} Item; 

so di poter memorizzare le dimensioni di name utilizzando una seconda variabile, ma esiste un altro modo?

i) c'è qualche altro vantaggio di utilizzare la dimensione fissa (1)

char name[40]; 

contro facendo quanto segue e con un puntatore a una matrice char (2)?

char *name; 

e se sì, qual è il vantaggio?

ii) Inoltre, la stringa che utilizza un puntatore a un array di caratteri (2) verrà memorizzata in modo sequenziale e immediatamente dopo la struttura (immediatamente dopo il puntatore alla stringa) o verrà memorizzata da qualche altra parte in memoria?

iii) Vorrei sapere come si può trovare la lunghezza di una variabile char * stringa (senza utilizzare un size_t, o valore intero per memorizzare la lunghezza)

+0

Perché questo tag è C++? – Rapptz

+0

@Rapptz: Suppongo perché il codice C++ spesso consuma ed espone API compatibili con C, dal momento che sono molto più compatibili con altri linguaggi –

+1

Per C++ è idiomatico usare 'std :: string' -' struct Foo {std :: string f; }; '. –

risposta

6

Ci sono fondamentalmente 3 convenzioni comuni per le stringhe. Tutti e tre si trovano in natura, sia per la rappresentazione in memoria che per la memorizzazione/trasmissione.

  1. Dimensioni fisse. L'accesso è molto efficiente, ma se la lunghezza effettiva varia sia lo spreco di spazio sia la necessità di uno dei seguenti metodi per determinare la fine del contenuto "reale".
  2. Lunghezza prefissata. Lo spazio extra è incluso nell'allocazione dinamica, per contenere la lunghezza. Dal puntatore puoi trovare sia il contenuto del personaggio che la lunghezza immediatamente precedente. Esempio: BSTR A volte la lunghezza è codificata per essere più efficiente in termini di spazio per le stringhe corte. Esempio: ASN-1
  3. Terminato. La stringa si estende fino alla prima occorrenza del carattere di terminazione (in genere NUL) e il contenuto non può contenere quel carattere. Le variazioni hanno reso la terminazione due NUL in sequenza, per consentire l'esistenza di singoli caratteri NUL nella stringa, che viene quindi spesso considerata come un elenco compresso di stringhe. Altre varianti usano una codifica come il riempimento di byte (anche UTF-8 funzionerebbe) per garantire che esista un codice riservato per la terminazione che non può mai apparire nella versione codificata del contenuto.

Nel terzo caso, c'è una funzione come strlen per cercare il terminatore e trovare la lunghezza.

Entrambi i casi che utilizzano i puntatori possono puntare a dati immediatamente successivi alla parte fissa della struttura, se lo si assegna con attenzione in quel modo.Se si desidera forzare questo, quindi utilizzare un array flessibile alla fine della struttura (nessun puntatore necessario). Come questo:

typedef struct 
{ 
    int damage; 
    char name[]; // terminated 
} Item; 

o

typedef struct 
{ 
    int damage; 
    int length_of_name; 
    char name[]; 
} Item; 
+0

Penso si chiami "flessibile", non "irregolare" e non è supportato da tutti i compilatori. – anatolyg

+0

@anatolyg: Grazie per quello. Penso che sia standard per C e illegale in C++? –

+0

@BenVoigt, AFAIK, sì, illegale in C++. – chris

0

Se si conosce la lunghezza massima della stringa è necessario, quindi è possibile utilizzare un array di caratteri. Significa però che userete più memoria di quella che normalmente usereste con array di caratteri allocati dinamicamente. Inoltre, dai un'occhiata a CString se stai usando C++. Puoi trovare la lunghezza dell'array di caratteri usando strlen. In caso di allocazione statica, credo che sarà una parte della variabile. La dinamica può essere ovunque sull'heap.

1
1) is there any other advantage to using the fixed size (1) 

char name[40]; 

versus doing the following and using a pointer to a char array (2)? 

char *name; 

and if so, what is the advantage? 

Con l'array dichiarato come char name[40]; spazio per il nome è già assegnato e si è liberi di copiare le informazioni in name da name[0] attraverso name[39]. Tuttavia, nel caso di char *name;, è semplicemente un puntatore di caratteri e può essere utilizzato per puntare a una stringa esistente in memoria, ma, da solo, non può essere utilizzato per copiare le informazioni finché non si assegna memoria per contenere tali informazioni. Quindi dire che avete una stringa di 30 caratteri che si desidera copiare name dichiarata come char *name;, è necessario prima allocare con malloc 30 caratteri più un carattere aggiuntivo per tenere il null di terminazione carattere:

char *name; 
name = malloc (sizeof (char) * (30 + 1)); 

Allora siete libero di copiare informazioni a/da name. Un vantaggio dell'allocazione dinamica è che è possibile la memoria realloc per name se le informazioni memorizzate nel nome aumentano. oltre 30 caratteri. Un ulteriore requisito dopo l'allocazione della memoria per name, è la responsabilità di liberare la memoria allocata quando non è più necessaria. Questo è uno schema approssimativo dei pro/contro/requisiti per l'utilizzo di uno in contrasto con l'altro.

Problemi correlati