2010-02-13 15 views
10

Ho difficoltà a capire come assegnare la memoria a un doppio puntatore. Voglio leggere un array di stringhe e memorizzarlo.Assegnare la memoria al doppio puntatore?

char **ptr; 
    fp = fopen("file.txt","r"); 
    ptr = (char**)malloc(sizeof(char*)*50); 
    for(int i=0; i<20; i++) 
    { 
     ptr[i] = (char*)malloc(sizeof(char)*50); 
     fgets(ptr[i],50,fp); 
    } 

invece di questo ho appena assegnare un grande blocco di memoria e memorizzare la stringa

char **ptr; 
    ptr = (char**)malloc(sizeof(char)*50*50); 

vorrei che essere sbagliato? E se è così, perché è?

+6

Non chiamarlo "puntatore doppio": questo ti porta fuori dal piede sbagliato mentalmente - è un puntatore a un puntatore. –

risposta

0

Un doppio puntatore è solo un puntatore a un altro puntatore. Così si può allocare in questo modo:

char *realptr=(char*)malloc(1234); 
char **ptr=&realptr; 

Bisogna tenere a mente dove il puntatore viene memorizzato (in questo esempio il puntatore punta doppi ad una variabile puntatore sullo stack in modo che sia valido dopo la funzione ritorna) .

-3

Il puntatore doppio è, semplicemente, un puntatore a un puntatore, In molti casi viene utilizzato come matrice di altri tipi.

Ad esempio, se si desidera creare un array di stringhe si può semplicemente fare:

char** stringArray = calloc(10, 40); 

questo creerà un array di dimensione 10, ogni elemento sarà una stringa di lunghezza 40.

quindi è possibile accedere a questo da stringArray [5] e ottenere una stringa in sesta posizione.

questo è uno uso, gli altri sono come menzionato sopra, un puntatore ad un puntatore, e possono essere assegnati semplicemente:

char* str = (char*)malloc(40); 
char** pointerToPointer = &str //Get the address of the str pointer, valid only in the current closure. 

maggiori qui: good array tutorial

+0

No, questo crea una singola matrice di 100 caratteri *, supponendo che char * impieghi 4 byte. –

+0

Quello che Hans dice è corretto. Ancor più, la matrice di 100 caratteri * viene inizializzata su 0 (poiché è stato utilizzato calloc), quindi tutti i caratteri * stanno puntando a null e l'accesso a tale posizione di matrice causerà un errore. –

10

Il secondo esempio è sbagliato perché ogni posizione di memoria concettualmente non regge un char* ma piuttosto un char. Se si cambia un po 'il vostro pensiero, si può aiutare con questo:

char *x; // Memory locations pointed to by x contain 'char' 
char **y; // Memory locations pointed to by y contain 'char*' 

x = (char*)malloc(sizeof(char) * 100); // 100 'char' 
y = (char**)malloc(sizeof(char*) * 100); // 100 'char*' 

// below is incorrect: 
y = (char**)malloc(sizeof(char) * 50 * 50); 
// 2500 'char' not 50 'char*' pointing to 50 'char' 

A causa di ciò, il primo ciclo sarebbe come si fa in C un array di caratteri array/puntatori. L'utilizzo di un blocco di memoria fisso per un array di matrici di caratteri è ok, ma si dovrebbe usare un singolo char* piuttosto che uno char**, poiché non si avrebbe alcun puntatore nella memoria, solo char s.

char *x = calloc(50 * 50, sizeof(char)); 

for (ii = 0; ii < 50; ++ii) { 
    // Note that each string is just an OFFSET into the memory block 
    // You must be sensitive to this when using these 'strings' 
    char *str = &x[ii * 50]; 
} 
+1

non dovrebbe essere l'ultima riga 'char * str = x + (ii * 50)'? – redFur

+2

E non trasmettere il risultato di 'malloc()'! –

1

altro modo semplice per memorizzare

Caso -1:

passo-1: char * p;

passo -2: prega di leggere è come qui di seguito

char (* p); ==> p è un puntatore a un char

ora basta fare malloc per il tipo (passo 2) senza bretelle

cioè p = malloc (sizeof (char) * some_len);

Caso -2:

step-1: char ** p;

passo -2:

prega di leggere è come qui di seguito

char * (* p); ==> p è un puntatore ad un char *

Ora non vi resta a fare malloc per il tipo (step-2) senza bretelle

cioè, p = malloc (sizeof (char *) * some_len) ;

Caso -3:

nessuno usa questo, ma solo per amore di spiegazione

char p ***;

letta come,

char ** (* p); ==> p è un puntatore a un carattere ** (e per questo caso di controllo 2 sopra)

p = malloc (sizeof (char **) * some_len);

0

Aggiungendo alla risposta di Pent, come ha giustamente sottolineato, non sarà possibile utilizzare questo doppio puntatore una volta che la funzione ritorna, perché indicherà una posizione di memoria sul record di attivazione della funzione sullo stack che ora è obsoleto (una volta che la funzione è tornata). Se si desidera utilizzare questo doppio puntatore dopo la funzione è tornato, si può fare questo:

char * realptr = (char *) malloc(1234); 
char ** ptr = (char **) malloc(sizeof(char *)); 
*ptr = realptr; 
return ptr; 

Il tipo di ritorno della funzione deve essere ovviamente char ** per questo.

Problemi correlati