2010-04-24 7 views
20

Supposons que je la struct et la fonction suivante renvoyant un pointeur:De retour un pointeur struct

typedef struct { 
    int num; 
    void *nums; 
    int size; 
} Mystruct; 

Mystruct *mystruct(int num, int size) 
{ 
    //Is the following correct? Is there a more efficient way? 
    Mystruct mystruct; 
    mystruct.num = num; 
    mystruct.size = size; 
    mystruct.nums = malloc(num*sizeof(size)); 
    Mystruct *my; 
    *my = mystruct; 
    return my; 
} 

Je veux définir tout pointeur myStruct en utilisant la fonction ci-dessus. Devrais-je déclarer une variable Mystruct, définir les propriétés de Mystruct, lui affecter un pointeur, et retourner le pointeur ou définir les propriétés d'une propriété mystruct via un pointeur immédiatement?

+1

Peut-être pourriez-vous coder les deux options. De la description, il n'est pas clair ce que vous avez l'intention. –

+0

Et rappelez-vous ... ne propagez jamais un pointeur "de la pile" vers le haut. –

Répondre

34

Dois-je déclarer une variable myStruct, définissent les propriétés de myStruct, attribuer un pointeur, et retourner le pointeur

Certainement pas, car la variable définie dans la fonction (en "auto" classe de stockage) disparaîtra lorsque la fonction se termine, et vous retournerez un pointeur qui pend.

Vous pouvez accepter un pointeur vers un Mystruct (la responsabilité de l'appelant d'allouer cela) et le remplir; ou, vous pouvez utiliser malloc pour en créer un nouveau (la responsabilité de l'appelant est de le libérer quand c'est fait). La deuxième option au moins vous permet de garder la signature de la fonction que vous semblez avoir envie:

Mystruct *mystruct(int num, int size) 
{ 
    Mystruct *p = malloc(sizeof(MyStruct)); 
    .... 
    return p; 
} 

mais il est souvent inférieure un - puisque l'appelant doit avoir des responsabilités de toute façon, peut aussi bien aller avec la première option et potentiellement gagner en performance (si l'appelant peut utiliser une instance de classe automatique car il sait que la portée d'utilisation est limitée).

+0

Pourquoi avez-vous catalogué malloc avec (Mystruct *)? Est-ce nécessaire? – idealistikz

+0

@idealistikz: Non, ce n'est pas nécessaire. – sth

+5

Il n'est pas nécessaire en C (et est souvent considéré comme un mauvais style dans cette langue) - mais l'inverse est vrai en C++. – caf

2

Allouer un nouveau Mystruct et en retournant un pointeur vers elle regarderait généralement plus ou moins comme ceci:

Mystruct *mystruct(int num, int size) 
{ 
    Mystruct *result; 

    result = malloc(sizeof(MyStruct)); 
    if (!result) 
    return NULL; 

    result->num = num; 
    ... 

    return result; 
} 

Plus tard, lorsque vous avez terminé avec le Mystruct alloué ici malloc, il devrait être libéré à nouveau avec free(). Le simple fait de déclarer une variable locale et de renvoyer un pointeur vers cette variable locale ne fonctionnera pas. La variable locale est hors de portée à la fin de la fonction et la mémoire où elle a été stockée est probablement réutilisée à d'autres fins. Le pointeur retourné pointera toujours vers l'emplacement de mémoire où se trouvait la variable locale, mais puisque cette variable n'existe plus, ce pointeur ne serait pas très utile.

2

Il est important de se rappeler que le pointeur n'est pas quelque chose que vous affectez à la structure, mais que le pointeur indique l'emplacement en mémoire que vous souhaitez traiter en tant que structure. En fonction de votre question, vous voulez vraiment allouer de la mémoire pour contenir la structure de données. Cela vous donne un pointeur vers l'emplacement de mémoire alloué. Une fois que vous avez cela, vous pouvez le retourner.


EDIT (après modification à la question originale) En regardant votre édition à la question, vous aurez certainement des problèmes avec le pointeur "mon". Ceci n'est pas initialisé et peut pointer n'importe où dans la mémoire. Lorsque vous tentez de copier la structure, vous aurez probablement une erreur de segmentation.

6

Vous ne pouvez pas utiliser la variable car elle sera désaffectée lorsque la fonction se termine.Par exemple:

Mystruct *mystruct(int num, int size) 
{ 
    MyStruct x; 
    x.num = 1; 
    ... 
    return &x; 
} 

donnera une erreur de segmentation ou de violation d'accès parce que la mémoire pour x est libérée dès que vous quittez. Il faut donc allouer de la mémoire à la structure (et être sûr de la libérer plus tard) ou déclarer un global qui restera à jamais. Exemple de ce dernier ...

Mystruct *mystruct(int num, int size) 
{ 
    MyStruct *x; 
    x = (MyStruct*)malloc(sizeof(MyStruct)); 
    x->num = 1; 
    ... 
    return x; 
} 
+2

en fait 'return * x' ne compilera pas dans la première fonction (j'imagine que vous voulez dire' return & x'? ** cela ** donnera l'erreur subtler que vous pensez, ou plus probablement des bogues encore plus subtils). –

+0

Oups, vous avez raison - retour & x. – staticman

2

Une autre façon de le faire ..

int mystruct(Mystruct *mystruct, int num, int size){ 
    if(mystruct == NULL) 
     return -1; 

    mystruct->num = num; 
    mystruct->size = size; 
    :: 
    return 0; 
} 

int main(){ 
    Mystruct my; 

    if(mystruct(&my, 3, 4) != 0){ 
     fprintf(stderr, "Cannot init!\n"); 
     exit(0); 
    } 
    :: 
} 
3

Si vous écrivez du code générique et vous ne savez pas comment il peut être utilisé, il est bon de fournir les deux options:

int mystructm(Mystruct *storage, int num, int size) 
{ 
    int rv = 0; 

    storage->num = num; 
    storage->size = size; 
    storage->nums = malloc(num*sizeof(size)); 
    if (!storage->nums) 
     return -1; 

    return 0; 
} 

Mystruct *mystruct(int num, int size) 
{ 
    Mystruct *mp = (Mystruct *)malloc(sizeof(Mystruct)); 
    if (mp) 
    { 
     if (mystructm(mp, num, size) == -1) 
     { 
      free(mp); 
      mp = NULL; 
     } 
    } 

    return mp; 
} 

l'idée est que comme un écrivain de la bibliothèque, vous ne devriez pas dicter la politique (telle que chaque myStruct doit être allouée de façon dynamique), mais devrait laisser l'auteur de l'application décider.

Questions connexes