2010-12-02 7 views
10

Je reçois une erreur de segmentation quand je passe les doubles pointeurs à la fonction pour initialiser la mémoireC: Comment passer un double pointeur vers une fonction

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

Comment puis-je passer les doubles pointeurs vers les fonctions .....

+1

essayer d'initialiser (& A, 10, 10) – Ibrahim

+0

Cela ne compilera pas sans changer initialize - '& A' est un' 'deux ***. –

Répondre

13

Si vous souhaitez modifier un pointeur en pointeur, vous devez passer un pointeur vers un pointeur.

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

Revisiter simplement mon C: si vous voulez modifier un pointeur en C, vous devez passer un pointeur sur un pointeur. Si vous devez modifier un pointeur sur un pointeur, vous devez passer un pointeur sur un pointeur vers un pointeur. Pourquoi? Donc pouvons-nous dire, si nous voulons modifier une valeur, nous devons également passer un pointeur à cette valeur? S'il vous plaît expliquer plus. Merci d'avance. – Unheilig

0

Eh bien pour une chose, la A initialize l'intérieur est une copie du A dans main - donc quand vous revenez à main, son A est encore non initialisée. Si vous essayez de l'utiliser - boom!

Pour passer à initialize « par référence », vous devez changer le type de paramètre à double*** et passer &A en main. Ensuite, lorsque vous l'utilisez dans initialize, vous devez le déréférencer à chaque fois, c'est-à-dire *A.

0
  1. Vous ne vérifiez pas les erreurs de mémoire insuffisante. Échouer.

  2. Vous passez BY VALUE une valeur non initialisée A pour initialiser(), puis l'initialiser. Mais de retour dans main(), cette variable locale A n'est toujours pas initialisée. Au lieu de cela, vous pourriez avoir initialize() retourne le double** (par exemple A = initialize(...)) ou modifier initialize() de sorte que son premier paramètre formel est un double ***pA que vous initialisez avec *pA = (double**)malloc(...);

+0

Re. (1), juste point, mais combien de programmes de jouets comme celui-ci ont jamais manqué de mémoire? –

+0

Et re.(2), vous semblez manquer certains niveaux d'indirection ... –

+0

Eh bien, voulez-vous conseiller aux débutants de vérifier les conditions de mémoire ou voulez-vous qu'ils apprennent à écrire des logiciels fragiles? S'il veut que A soit initialisé en tant que paramètre out de initialize(), il doit passer un double ***, qui est alors utilisé comme (* pA) partout où A est apparu dans l'original –

13

Comme d'autres l'ont dit, vous devez prendre un pointeur pour pointer vers un pointeur dans votre fonction init. Voici comment les changements de fonction initialize:

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

Et main seront:

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

En outre, le code que vous avez publié il ne devrait pas provoquer une erreur de segmentation lors du passage du pointeur A dans la faille de segmentation. le plus probable se produit lorsque vous revenez de la fonction et essayez d'accéder à A, car le A dans main n'aura pas été initialisé. Seule une copie est initialisée comme vous le faites et cette copie est locale à la fonction initialize, elle est donc perdue à votre retour.

+0

@LVlad Hi, bonne réponse. Revisiter simplement mon C: si vous voulez modifier un pointeur en C, vous devez passer un pointeur sur un pointeur. Si vous devez modifier un pointeur sur un pointeur, vous devez passer un pointeur sur un pointeur vers un pointeur. Pourquoi? Donc pouvons-nous dire, si nous voulons modifier une valeur, nous devons également passer un pointeur à cette valeur? S'il vous plaît expliquer plus. Merci d'avance. – Unheilig

+0

HI Unheilig, cela est lié à l'appel par référence. Par exemple (un certain type) * A Alors s'il est nécessaire de modifier un type à un endroit autre que celui où A est actuellement défini, vous devrez passer l'adresse de A et devrez derefrencer l'adresse passée dans la fonction appelée. La raison de passer l'adresse est que la fonction appelée obtient sa pile distincte dans l'espace d'adressage du processus. Dans le problème ci-dessus, A défini dans main() est dans une pile séparée et n'est jamais accessible par initialize(). Il n'y a rien de mal signalé si A n'est pas retourné dans main(). –

+0

Merci beaucoup, je me bats avec lui pendant 3 jours. –

0

C'est le genre de chose que vous ne voulez pas faire. Au lieu d'utiliser inutilement un argument out pour cela, allouer dans la fonction et retourner le résultat. Pour ce faire, à la place:

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

Vous avez oublié de mettre à jour le type de retour de 'initialize' et de renvoyer une valeur. –

Questions connexes