2012-01-31 11 views
7

Diciamo che avere-dotazione di memoria per array di caratteri

struct Person { 
    char *name; 
    int age; 
    int height; 
    int weight; 
}; 

Se DO-

struct Person *who = malloc(sizeof(struct Person)); 

Come avrebbe C sapere quanta memoria da allocare per nome variabile come questo può contenere un gran numero di dati/stringa? Sono nuovo di C e confuso con l'allocazione della memoria.

+0

Non provare a scrivere file sorgente multilingue. Credo che il modo idiomatico di gestire la memoria in C++ sia con [RAII] (http://en.wikipedia.org/wiki/RAII). – pmg

+1

No, 'name' è solo un puntatore, che ha una dimensione distinta (di solito 4 o 8 byte). Una volta capito questo, ce l'hai. –

risposta

4

Non saprà, sarà necessario allocare memoria separatamente.

struct Person *who = malloc(sizeof(struct Person)); 

alloca memoria sufficiente per memorizzare un oggetto di tipo Person.
All'interno di un oggetto Person il membro name occupa solo uno spazio equivalente alla dimensione di un puntatore a char.
Il precedente numero malloc assegna solo molto spazio, per essere in grado di fare qualcosa di significativo con il puntatore del membro che dovrete allocare memoria ad esso separatamente.

#define MAX_NAME 124 
who->name = malloc(sizeof(char) * MAX_NAME); 

Ora l'organo name indica una memoria dinamica di dimensione 124 byte sul mucchio e può essere riutilizzato.

Inoltre, una volta eseguito l'utilizzo, è necessario ricordarsi di free in modo esplicito o si finisce con una perdita di memoria.

free(who->name); 
free(who); 
+4

Presumo che Q sia invalidato con tag 'C++' dal momento che l'OP dice * Come sarebbe C .... * e * Sono nuovo di C ... * Se la Q è C++, la risposta è abbastanza simile a usare un ' std :: STRING'. –

+0

L'ho taggato in C++ perché ritengo che abbiano somiglianza quando si parla di gestione della memoria. O mi sbaglio? Sono nuovo di C ma non nuovo per la programmazione in generale. Grazie per la risposta super veloce. – DragonBorn

+2

@ZiG Ci sono davvero delle somiglianze (anche se preferireste usare 'new' su' malloc'). Ma in C++ spesso non si ha a che fare con una gestione della memoria di basso livello, ad es. usando 'std :: string' per le stringhe, invece di semplici array di caratteri (o puntatori), o usando' std :: vector' invece di matrici dinamiche create dall'utente. –

-2

Penso che si dovrebbe anche avere bisogno di allocare memoria per l'attributo name

0

E non lo fa. Devi farlo anche tu.

struct Person *who = malloc(sizeof(struct Person)); 
who->name = malloc(sizeof(char) * 16); /* for a 15+1 character array */ 
0

Si dispone di un puntatore a un nome di matrice di caratteri nella struttura, vale a dire. consumerà così tanti byte che sono necessari per rappresentare un indirizzo di memoria.

Se si desidera utilizzare effettivamente il campo, è necessario allocare memoria aggiuntiva per esso.

0

Assegnerà 4 byte per il puntatore name, ma nessuno spazio per la stringa "reale". Se provi a scrivere lì, seg segnerà l'errore; è necessario malloc (e free) separatamente.

Utilizzando string (in C++) si può risparmiare qualche mal di testa

+0

Immagino che allocherebbe 8B su macchine 64b :) – Vyktor

+0

Blah, a destra:) –

2

Il name membro è solo un puntatore. La dimensione di un puntatore varia con l'architettura sottostante, ma di solito è di 4 o 8 byte al giorno d'oggi.

I dati che name può indicare (se assegnato in seguito) devono essere disposti in un'area che non coincide con lo struct.

A livello di lingua, struct non sa nulla della memoria a cui punta il membro name; devi gestirlo manualmente.

0

Per i puntatori alla struttura viene allocata memoria sufficiente per il puntatore. Devi creare la memoria per il char * e assegnare il valore alla struct. Dando per scontato che aveva char* name da qualche parte:

struct Person *who = malloc(sizeof(struct Person)); 
who->name = malloc((strlen(name)+1) * sizeof(char)); 
strcpy(who->name, name) 
+0

Potrei semplicemente usare 'stdup' per creare' who-> nome'. –

+0

Suppongo tu intenda strdup? Potresti se è disponibile ma non fa parte dello standard ANSI C. Questo esempio di codice dovrebbe essere valido ANSI C –

+0

Mai menzionato nella domanda che è richiesto ANSI C valido. Un sacco di implementazioni includono questa routine che può essere optomised. –

0

membri Pointer occupano una parola nella mia esperienza (l'indirizzo su strega risiedono i dati), quindi la dimensione sarà probabilmente 16 byte (assumendo una parola è 4 byte)

Come l'uomo ha detto sopra è necessario allocare separatamente memoria per * nome strega libererà memoria da qualche altra parte per la dimensione desiderata

3

Non dare per scontato che la memoria che memorizza il puntatore per il nome sia la stessa della memoria che memorizza dati per nome. Assumendo una dimensione della parola di 4 byte, si dispone quanto segue:

  • char * (4 bytes)
  • int (4 bytes)
  • int (4 bytes)
  • int (4 bytes)
  • ================
  • total: 16 bytes

che è: sizeof(char*) + sizeof(int) + sizeof(int) + sizeof(int). C conosce la dimensione perché gli hai detto la dimensione degli elementi nella definizione della struct.

Penso che quello che si sono confusi su è la seguente:

Il contenuto del char * sarà una posizione di memoria (ad esempio 0x00ffbe532), che è dove verrà memorizzato la stringa effettiva. Non dare per scontato che il contenuto della struct sia contiguo (a causa del puntatore). In effetti, puoi essere abbastanza sicuro che non lo saranno.

Quindi, per ribadire, per un esempio struct Person (questo è solo un esempio, le posizioni non saranno gli stessi in un programma vero e proprio.)

  • location : [contents]
  • 0x0000 : [0x00ffbe532]
  • 0x0004 : [10]
  • 0x0008 : [3]
  • 0x000C : [25]

  • 0x00ffbe532 : [I am a string\0]

+0

+1 per la risposta dettagliata. Grazie. – DragonBorn

+1

Si prega di non firmare i tuoi messaggi. –

2

alloca memoria per il proprio l'puntatore a char. È necessario eseguire un'assegnazione separata per i contenuti.

ci sono altre opzioni, anche se:

Se siete OK con avere una lunghezza massima fissa di dimensioni, si può fare:

struct Person { 
    char name[PERSON_NAME_MAX_LENGTH+1]; 
    int age; 
    int height; 
    int weight; 
}; 

e allocare come nel tuo esempio.

Oppure si può dichiarare un variable sized struct, ma io non lo consiglio, è che è difficile e non si può avere più di un array di dimensioni variabili per struct:

struct Person { 
    int age; 
    int height; 
    int weight; 
    char name[]; /*this must go at the end*/ 
}; 

e poi allocare le cose come:

struct Person *who = malloc(sizeof(struct Person) + sizeof(char)*(name_length+1)); 
Problemi correlati