2010-02-13 33 views
10

Tengo problemas para entender cómo asignar la memoria a un doble puntero. Quiero leer una matriz de cadenas y almacenarla.¿Asignar memoria al puntero doble?

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); 
    } 

en lugar de esto que acabo de asignar un bloque grande de memoria y tienda de la cadena

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

habría que estar mal? Y si es así, ¿por qué es?

+6

No lo llame un "doble puntero" - esto lo lleva mal con el pie mentalmente - es un puntero a un puntero. –

Respuesta

0

Un puntero doble es solo un puntero a otro puntero. Por lo que puede asignarlo como esto:

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

Hay que tener en cuenta cuando el puntero se almacena en (en este ejemplo el puntero apunta dobles a una variable puntero de la pila por lo que es válido después de la función devuelve) .

-3

Puntero doble es, simplemente, un puntero a un puntero, En muchos casos se utiliza como una matriz de otros tipos.

Por ejemplo, si desea crear una matriz de cadenas puede simplemente hacer:

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

esto creará una matriz de tamaño 10, cada elemento habrá una cadena de longitud 40.

por lo que puede acceder a esto por stringArray [5] y obtener una cadena en la 6ª posición.

este es un uso, los otros son como se mencionó anteriormente, un puntero a un puntero, y se pueden asignar simplemente por:

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

leer más aquí: good array tutorial

+0

No, esto crea una única matriz de 100 char *, suponiendo que char * tome 4 bytes. –

+0

Lo que Hans dice es correcto. Aún más, la matriz de 100 char * se inicializa en 0 (ya que usó calloc) por lo que todos esos char * están apuntando a nulo y acceder a la ubicación de la matriz provocará un error. –

10

Su segundo ejemplo es mal porque cada ubicación de memoria conceptualmente no tendría un char*, sino más bien un char. Si cambia un poco su forma de pensar, puede ayudar con esto:

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' 

Debido a eso, el primer bucle sería la forma en que se hace en C un conjunto de matrices de caracteres/punteros. Usar un bloque de memoria fijo para una matriz de matrices de caracteres está bien, pero usaría un solo char* en lugar de un char**, ya que no tendría ningún puntero en la 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

¿No debería ser la última línea 'char * str = x + (ii * 50)'? – redFur

+2

Y no eche el resultado de 'malloc()'! –

1

otra manera más sencilla de memorizar

Case -1:

paso 1: char * p;

paso -2: favor leerlo, como a continuación

char (* p); ==> p es un puntero a un char

ahora sólo tiene que hacer malloc para el tipo (paso 2) sin aparatos

es decir, p = malloc (sizeof (char) * some_len);

Case -2:

paso 1: char ** p;

paso -2:

favor leerlo, como a continuación

char * (* p); ==> p es un puntero a un char *

Ahora sólo tiene que ver malloc para el tipo (paso 2) sin aparatos

es decir, p = malloc (sizeof (char *) * some_len) ;

Caso -3:

Nadie utiliza esto, pero sólo por el bien de la explicación

carbón *** p;

leerlo como,

char ** (* p); ==> p es un puntero a un char ** (y para este check case-2 arriba)

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

0

Agregando a la respuesta de Pent, como señaló correctamente, no podrá utilizar este doble puntero una vez que la función regrese, porque apuntará a una ubicación de memoria en el registro de activación de la función en la pila que ahora está obsoleto (una vez que la función ha regresado). Si desea utilizar este doble puntero después de la función ha vuelto, es posible hacer esto:

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

El tipo de retorno de la función debe ser obviamente char ** para esto.