2010-12-02 37 views
10

Recibo un fallo de segmentación cuando paso los dobles punteros a la función para inicializar la memoriaC: ¿Cómo pasar un doble puntero a una función

int main() 
{ 
    double **A; 
    initialize(A, 10, 10); 
...... 
} 

void initialize(double **A, int r, int c) 
{ 
    A = (double **)malloc(sizeof(double *)*r); 
    for(int i = 0; i< r; i++) { 
     A[i] = (double *)malloc(sizeof(double) *c); 
     for(int j = 0; j < c; j++) { 
      A[i][j] = 0.0; 
     } 
    } 
} 

¿Cómo puedo pasar los dobles punteros a las funciones .....

+1

intentar inicializar (& A, 10, 10) – Ibrahim

+0

Eso no se compilará sin cambiar inicializar - '& A' es un' 'doble ***. –

Respuesta

13

Si desea modificar un puntero a puntero, debe pasar un puntero a puntero a puntero.

void func(double ***data) { *data = malloc(sizeof(double*)*10); for.... }; 
double ** data; func(&data); 
+1

Acabo de volver a visitar mi C: si desea modificar un puntero en C, debe pasar un puntero a un puntero. Si necesita modificar un puntero a un puntero, debe pasar un puntero a un puntero a un puntero. ¿Por qué? Entonces, ¿podemos decir que si queremos modificar un valor, también debemos pasar un puntero a ese valor? Por favor explica más Gracias por adelantado. – Unheilig

0

Bien para una cosa, la A dentro de inicializar es una copia de la A en main - así que cuando vuelvas a main, su A todavía no inicializado. Si intentas usarlo, ¡boom!

pasarlo a initialize 'referencia', es necesario cambiar el tipo de parámetro a double*** y pase &A en main. Luego, cuando lo usa en initialize, necesita desreferenciarlo cada vez, es decir, *A.

0
  1. No está comprobando si hay errores de falta de memoria. Fallar.

  2. Pasa POR VALOR un valor A sin inicializar para inicializar() y luego inicializarlo. Pero de vuelta en main(), esa variable local A aún no está inicializada. En su lugar puede que tenga initialize() devuelve el double** (por ejemplo A = initialize(...)) o modificar initialize() por lo que su primer parámetro formal es una double ***pA que inicializar con *pA = (double**)malloc(...);

+0

Re. (1), punto justo, pero ¿cuántos programas de juguete como este se han quedado alguna vez sin memoria? –

+0

Y re.(2), parece que le faltan algunos niveles de indirección ... –

+0

Bueno, ¿quiere aconsejar a los principiantes que verifiquen si hay problemas de memoria o si quieren que aprendan a escribir software frágil? Si quiere que A se inicialice como un parámetro de salida de initialize(), necesita pasar un doble ***, que luego se usa como (* pA) donde aparezca A en el original –

13

Como otros han dicho, es necesario tener un puntero puntero a puntero en su función init. Así es como los cambios initialize función:

void initialize(double ***A, int r, int c) 
{ 
    *A = (double **)malloc(sizeof(double *)*r); 
    for(int i = 0; i< r; i++) { 
     (*A)[i] = (double *)malloc(sizeof(double) *c); 
     for(int j = 0; j < c; j++) { 
      (*A)[i][j] = 0.0; 
     } 
    } 
} 

Y main serán:

int main() 
{ 
    double **A; 
    initialize(&A, 10, 10); 
} 

Además, el código que usted envió debería causar ninguna violación de segmento al pasar el puntero del A en el fallo de segmentación. lo más probable es que ocurra cuando regrese de la función e intente acceder al A, porque el A en main no se habrá inicializado. Solo una copia de la misma se inicializa de la manera en que lo hace, y esa copia es local para la función initialize, por lo que se perderá cuando regrese.

+0

@LVlad Hola, buena respuesta. Simplemente revisando mi C: si quiere modificar un puntero en C, necesita pasar un puntero a un puntero. Si necesita modificar un puntero a un puntero, debe pasar un puntero a un puntero a un puntero. ¿Por qué? Entonces, ¿podemos decir que si queremos modificar un valor, también debemos pasar un puntero a ese valor? Por favor explica más Gracias por adelantado. – Unheilig

+0

HI Unheilig, esto está relacionado con la llamada por referencia. Por ejemplo (algún tipo) * A entonces, si es necesario modificar algún tipo en un lugar distinto al que A está actualmente definido, deberá pasar la dirección de A y requerirá la eliminación de la dirección pasada en la función llamada. La razón para pasar la dirección es que la función llamada obtiene su pila separada en el espacio de direcciones del proceso. En el problema anterior, A definido en main() está en una pila separada y nunca se accede mediante initialize(). No se informa nada incorrecto si no se accede a A en main(). –

+0

Muchas gracias, estoy luchando con eso por 3 días. –

0

Este es el tipo de cosas que no desea hacer. En lugar de usar innecesariamente un argumento de salida para esto, asigne la función y devuelva el resultado. Hacer esto en su lugar:

int main() 
{ 
    double **A; 
    A = initialize(A10, 10); 
} 

double** initialize(int r, int c) 
{ 
    double **A; 
    A = malloc(sizeof(double *)*r); 
    for(int i = 0; i< r; i++) { 
     A[i] = (double *)malloc(sizeof(double) *c); 
     for(int j = 0; j < c; j++) { 
      A[i][j] = 0.0; 
     } 
    } 
    return A; 
} 
+0

Olvidó actualizar el tipo de devolución de 'initialize', y realmente devuelve un valor. –

Cuestiones relacionadas