5 votes

ne rien retourner d'une fonction non vide en C

Ce qui est considéré comme une bonne pratique dans l'extrait suivant :

int foo(struct data *bar, struct info bla) {
    if (!bar) {
        bla->status = 0;
        return;
    }
    ...
}

En fait, ça fonctionne bien. Mais je me sens mal à l'aise avec gcc en me donnant un avertissement.


Voici le code actuel :

static int pop(struct stack **stack, struct info *info) {
        int ret;
        struct stack *tmp;

        if (!*stack) {
                info->error = 0;
                return;
        }

        ret = (*stack)->data;
        tmp = *stack;
        *stack = (*stack)->next;
        free(tmp);

        return ret;
}

0voto

vpit3833 Points 4435
int main(void)
{
    printf("hello world\n");
}

rendements 10. L'interpréteur de commandes bash sur Mac OS X le confirme. C'est-à-dire que chaque int Une fonction de retour renvoie quelque chose, il devrait en être de même pour les fonctions qui renvoient d'autres types. Si vous ne retournez pas explicitement, quelque chose que vous ne connaissez pas sera retourné. Si vous n'êtes pas en mesure de retourner quelque chose à la fin de la fonction, essayez de retourner void pour voir si cela casse le code. Si c'est le cas, la fonction doit être retravaillée, sinon, continuez à utiliser le type de retour void.

0voto

PeterK Points 4218

J'envisagerais d'ajouter un troisième paramètre qui serait en fait la "valeur de retour" et au lieu de renvoyer le résultat de la fonction, je renverrais simplement son état, qui pourrait être un enum par exemple ( et vous pourriez avoir "STATUS_OK", "STATUS_FAIL", "STATUS_NO_RESULT" etc...).

Cela sera compréhensible pour toute personne utilisant votre fonction et fournira en même temps le comportement souhaité (par exemple, ne pas renvoyer de valeur signifierait ne pas toucher le troisième paramètre et renvoyer "STATUS_NO_RESULT").

0voto

ShinTakezou Points 5603

Puisque vous utilisez info->error pour dire si la fonction a échoué ou non, vous pouvez retourner ce que vous voulez, puisque l'appelant doit ignorer la valeur de retour. Vous pouvez donc taire l'avertissement avec return -1 , return 0 , return MAGIC_NUMBER ... ...

En général, les fonctions sont codées de la manière inverse : la valeur de retour indique si la fonction a réussi ou non. Si toutes les valeurs de retour int sont bonnes, vous pouvez écrire la fonction de manière à ce qu'elle renvoie un échec ou un succès, et en cas de succès, vous remplissez les données. Dans votre cas, votre structure d'information pourrait contenir un int data ou vous pouvez ajouter une autre arg au func.

De cette façon, l'appelant peut faire quelque chose comme

if ( pop(stack, info) == SUCCESS ) {
  // ...
  printf("%d\n", info->data);
} else { /* failure */
  // info->data holds no data, but info->error could be an error code, e.g.
  fprintf(stderr, "can't pop: %s\n", error_msg[info->error]);
}

L'utilisation dans votre cas est moins intuitive :

data = pop(stack, info);
if (info->error != ERROR) {
  // data is valid
} else {
  // data is garbage and we have to say an error occurred.
}

BTW, vous ne mettez pas info->error à quelque chose de différent par 0, donc votre code est potentiellement bogué ; par exemple

  info->error = 0;
  data = pop(stack, info);

déclencherait toujours une erreur, même si la pile est effectivement correcte et que les données sont donc valides.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X